All of lore.kernel.org
 help / color / mirror / Atom feed
* How to add "Service Changed Indication"
@ 2021-01-24  8:42 Kenny Bian
  2021-01-25  3:35 ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 8+ messages in thread
From: Kenny Bian @ 2021-01-24  8:42 UTC (permalink / raw)
  To: linux-bluetooth

Hello,

We implemented a GATT server on Linux in Python. The code is based on
the code sample(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
The BlueZ version is 5.48. But we found a problem. The cached data in
/var/lib/bluetooth caused the mobile app to crash if some
characteristics are changed. After some research, we found "Under BLE
standard 'Generic Attribute'(0x1801), there is a Characteristic
'Service Changed' (0x2A05) with 'indicate' property", see
https://github.com/espressif/esp-idf/issues/1777.

The questions we have:
How to enable the "Service Changed Indication"(0x2A05) in the
bluetooth? Is there any code example in Python?

Thanks in advance!

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

* Re: How to add "Service Changed Indication"
  2021-01-24  8:42 How to add "Service Changed Indication" Kenny Bian
@ 2021-01-25  3:35 ` Luiz Augusto von Dentz
  2021-01-25  6:41   ` Kenny Bian
  0 siblings, 1 reply; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2021-01-25  3:35 UTC (permalink / raw)
  To: Kenny Bian; +Cc: linux-bluetooth

Hi Kenny,

On Sun, Jan 24, 2021 at 12:45 AM Kenny Bian <kennybian@gmail.com> wrote:
>
> Hello,
>
> We implemented a GATT server on Linux in Python. The code is based on
> the code sample(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> The BlueZ version is 5.48. But we found a problem. The cached data in
> /var/lib/bluetooth caused the mobile app to crash if some
> characteristics are changed. After some research, we found "Under BLE
> standard 'Generic Attribute'(0x1801), there is a Characteristic
> 'Service Changed' (0x2A05) with 'indicate' property", see
> https://github.com/espressif/esp-idf/issues/1777.
>
> The questions we have:
> How to enable the "Service Changed Indication"(0x2A05) in the
> bluetooth? Is there any code example in Python?

If you are registering the services with Bluetoothd then it should
generate the service change automatically:

https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1185

When a new service is registered it is indicated here:

https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1452


-- 
Luiz Augusto von Dentz

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

* Re: How to add "Service Changed Indication"
  2021-01-25  3:35 ` Luiz Augusto von Dentz
@ 2021-01-25  6:41   ` Kenny Bian
  2021-01-25 17:58     ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 8+ messages in thread
From: Kenny Bian @ 2021-01-25  6:41 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

Thank you so much for your reply. I appreciate it.

By "registering the services", do you mean "RegisterApplication()" in
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server#n656?
If that is the case, I believe I already registered the services.
I checked the files in /var/lib/bluetooth. According to
https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/settings-storage.txt#n321,
there should be a "[ServiceChanged]" section in the "info" file. But I
don't see it in the "info" file. Is there a way to tell the "Service
Changed Indication" is actually working?
Let's suppose the "Service Changed Indication" is already enabled, is
there a way for the mobile app to check on their side to tell which
service(s) got changed?

Thanks again for your help.

On Sun, Jan 24, 2021 at 7:35 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Hi Kenny,
>
> On Sun, Jan 24, 2021 at 12:45 AM Kenny Bian <kennybian@gmail.com> wrote:
> >
> > Hello,
> >
> > We implemented a GATT server on Linux in Python. The code is based on
> > the code sample(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> > The BlueZ version is 5.48. But we found a problem. The cached data in
> > /var/lib/bluetooth caused the mobile app to crash if some
> > characteristics are changed. After some research, we found "Under BLE
> > standard 'Generic Attribute'(0x1801), there is a Characteristic
> > 'Service Changed' (0x2A05) with 'indicate' property", see
> > https://github.com/espressif/esp-idf/issues/1777.
> >
> > The questions we have:
> > How to enable the "Service Changed Indication"(0x2A05) in the
> > bluetooth? Is there any code example in Python?
>
> If you are registering the services with Bluetoothd then it should
> generate the service change automatically:
>
> https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1185
>
> When a new service is registered it is indicated here:
>
> https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1452
>
>
> --
> Luiz Augusto von Dentz

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

* Re: How to add "Service Changed Indication"
  2021-01-25  6:41   ` Kenny Bian
@ 2021-01-25 17:58     ` Luiz Augusto von Dentz
  2021-01-27  8:42       ` Kenny Bian
  0 siblings, 1 reply; 8+ messages in thread
From: Luiz Augusto von Dentz @ 2021-01-25 17:58 UTC (permalink / raw)
  To: Kenny Bian; +Cc: linux-bluetooth

Hi Kenny,

On Sun, Jan 24, 2021 at 10:42 PM Kenny Bian <kennybian@gmail.com> wrote:
>
> Hi Luiz,
>
> Thank you so much for your reply. I appreciate it.
>
> By "registering the services", do you mean "RegisterApplication()" in
> https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server#n656?
> If that is the case, I believe I already registered the services.
> I checked the files in /var/lib/bluetooth. According to
> https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/settings-storage.txt#n321,
> there should be a "[ServiceChanged]" section in the "info" file. But I
> don't see it in the "info" file. Is there a way to tell the "Service
> Changed Indication" is actually working?
> Let's suppose the "Service Changed Indication" is already enabled, is
> there a way for the mobile app to check on their side to tell which
> service(s) got changed?

HCI traces (btmon) should be able to tell you if it has been
subscribed or not, if there is an Indication in it it probably means
the remote has subscribed.

> Thanks again for your help.
>
> On Sun, Jan 24, 2021 at 7:35 PM Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> >
> > Hi Kenny,
> >
> > On Sun, Jan 24, 2021 at 12:45 AM Kenny Bian <kennybian@gmail.com> wrote:
> > >
> > > Hello,
> > >
> > > We implemented a GATT server on Linux in Python. The code is based on
> > > the code sample(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> > > The BlueZ version is 5.48. But we found a problem. The cached data in
> > > /var/lib/bluetooth caused the mobile app to crash if some
> > > characteristics are changed. After some research, we found "Under BLE
> > > standard 'Generic Attribute'(0x1801), there is a Characteristic
> > > 'Service Changed' (0x2A05) with 'indicate' property", see
> > > https://github.com/espressif/esp-idf/issues/1777.
> > >
> > > The questions we have:
> > > How to enable the "Service Changed Indication"(0x2A05) in the
> > > bluetooth? Is there any code example in Python?
> >
> > If you are registering the services with Bluetoothd then it should
> > generate the service change automatically:
> >
> > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1185
> >
> > When a new service is registered it is indicated here:
> >
> > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1452
> >
> >
> > --
> > Luiz Augusto von Dentz



-- 
Luiz Augusto von Dentz

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

* Re: How to add "Service Changed Indication"
  2021-01-25 17:58     ` Luiz Augusto von Dentz
@ 2021-01-27  8:42       ` Kenny Bian
  2021-01-27  8:46         ` Kenny Bian
  0 siblings, 1 reply; 8+ messages in thread
From: Kenny Bian @ 2021-01-27  8:42 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

Thank you so much for your information.

I created a test GATT server from the sample
code(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
I have 2 python scripts. In the "bt_read.py" I created, the Heart Rate
Measurement(2A37) and Body Sensor Location(2A38) only have Read
attribute. In the "bt_notify.py" I created, the Heart Rate
Measurement(2A37) and Body Sensor Location(2A38) only have both the
Read and Notify attribute.

Here is what I did:
I ran the "bt_read.py" and captured the btmon log. Then I ran
"bt_notify.py" and captured the btmon log. I read both logs. But I
don't see there is any info regarding the "Service Changed
Indication".

Here is the btmon log with both the Read and Notify attributes below.
Thanks again for your help!
=========================================================================
Bluetooth monitor ver 5.48
= Note: Linux version 4.19.35-g92e18fefc77 (armv7l)                    0.809169
= Note: Bluetooth subsystem version 2.22                               0.809182
= New Index: 00:16:A4:4A:2D:27 (Primary,UART,hci0)              [hci0] 0.809187
= Open Index: 00:16:A4:4A:2D:27                                 [hci0] 0.809190
= Index Info: 00:16:A4:4.. (Cypress Semiconductor Corporation)  [hci0] 0.809194
@ MGMT Open: bluetoothd (privileged) version 1.14             {0x0002} 0.809200
@ MGMT Open: bluetoothd (privileged) version 1.14             {0x0001} 0.809203
@ MGMT Open: btmon (privileged) version 1.14                  {0x0003} 0.809276
> ACL Data RX: Handle 65 flags 0x02 dlen 8                   #1 [hci0] 4.543721
      ATT: Handle Value Notification (0x1b) len 3
        Handle: 0x0016
          Data: 64
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #2 [hci0] 6.883753
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0001-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 30                  #3 [hci0] 6.884412
      ATT: Read By Group Type Response (0x11) len 25
        Attribute data length: 6
        Attribute group list: 4 entries
        Handle range: 0x0001-0x0005
        UUID: Generic Access Profile (0x1800)
        Handle range: 0x0006-0x0009
        UUID: Generic Attribute Profile (0x1801)
        Handle range: 0x0234-0x023c
        UUID: Heart Rate (0x180d)
        Handle range: 0x023d-0x0240
        UUID: Battery Service (0x180f)
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #4 [hci0] 6.944638
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0241-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 26                  #5 [hci0] 6.945293
      ATT: Read By Group Type Response (0x11) len 21
        Attribute data length: 20
        Attribute group list: 1 entry
        Handle range: 0x0241-0x0250
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef0)
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #6 [hci0] 7.004723
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0251-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 9                   #7 [hci0] 7.005369
      ATT: Error Response (0x01) len 4
        Read By Group Type Request (0x10)
        Handle: 0x0251
        Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5       #8 [hci0] 7.005549
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #9 [hci0] 7.064450
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0234-0x023c
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 27                 #10 [hci0] 7.065112
      ATT: Read By Type Response (0x09) len 22
        Attribute data length: 7
        Attribute data list: 3 entries
        Handle: 0x0235
        Value: 123602372a
        Handle: 0x0238
        Value: 123902382a
        Handle: 0x023b
        Value: 083c02392a
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #11 [hci0] 7.124428
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x023d-0x0240
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 13                 #12 [hci0] 7.125226
      ATT: Read By Type Response (0x09) len 8
        Attribute data length: 7
        Attribute data list: 1 entry
        Handle: 0x023e
        Value: 123f02192a
> HCI Event: Number of Completed Packets (0x13) plen 5      #13 [hci0] 7.125376
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #14 [hci0] 7.184416
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0241-0x0250
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 69                 #15 [hci0] 7.185101
      ATT: Read By Type Response (0x09) len 64
        Attribute data length: 21
        Attribute data list: 3 entries
        Handle: 0x0242
        Value: 8a4302f1debc9a785634127856341278563412
        Handle: 0x0247
        Value: 8a4802f3debc9a785634127856341278563412
        Handle: 0x024c
        Value: 8a4d02f5debc9a785634127856341278563412
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #16 [hci0] 7.244526
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x024e-0x0250
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 9                  #17 [hci0] 7.246144
      ATT: Error Response (0x01) len 4
        Read By Type Request (0x08)
        Handle: 0x024e
        Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5      #18 [hci0] 7.246564
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #19 [hci0] 7.304500
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0237-0x0237
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #20 [hci0] 7.305951
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0237
        UUID: Client Characteristic Configuration (0x2902)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #21 [hci0] 7.364540
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x023a-0x023a
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #22 [hci0] 7.366242
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x023a
        UUID: Client Characteristic Configuration (0x2902)
> HCI Event: Number of Completed Packets (0x13) plen 5      #23 [hci0] 7.366660
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #24 [hci0] 7.424617
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0240-0x0240
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #25 [hci0] 7.426085
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0240
        UUID: Client Characteristic Configuration (0x2902)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #26 [hci0] 7.484523
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0244-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #27 [hci0] 7.486104
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0244
        UUID: Characteristic Extended Properties (0x2900)
> HCI Event: Number of Completed Packets (0x13) plen 5      #28 [hci0] 7.486520
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #29 [hci0] 7.544546
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0245-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #30 [hci0] 7.546011
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x0245
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef2)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #31 [hci0] 7.604713
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0246-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #32 [hci0] 7.606323
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0246
        UUID: Characteristic User Description (0x2901)
> HCI Event: Number of Completed Packets (0x13) plen 5      #33 [hci0] 7.606747
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #34 [hci0] 7.664243
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0249-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #35 [hci0] 7.665862
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0249
        UUID: Characteristic Extended Properties (0x2900)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #36 [hci0] 7.724603
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024a-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #37 [hci0] 7.726315
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x024a
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef4)
> HCI Event: Number of Completed Packets (0x13) plen 5      #38 [hci0] 7.726625
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #39 [hci0] 7.784545
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024b-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #40 [hci0] 7.785996
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x024b
        UUID: Characteristic User Description (0x2901)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #41 [hci0] 7.844187
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024e-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #42 [hci0] 7.845777
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x024e
        UUID: Characteristic Extended Properties (0x2900)
> HCI Event: Number of Completed Packets (0x13) plen 5      #43 [hci0] 7.846215
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #44 [hci0] 7.904466
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024f-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #45 [hci0] 7.906160
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x024f
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef6)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #46 [hci0] 7.964493
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0250-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #47 [hci0] 7.966067
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0250
        UUID: Characteristic User Description (0x2901)
> HCI Event: Number of Completed Packets (0x13) plen 5      #48 [hci0] 7.966489
        Num handles: 1
        Handle: 65
        Count: 2
> HCI Event: Number of Completed Packets (0x13) plen 5      #49 [hci0] 8.203559
        Num handles: 1
        Handle: 65
        Count: 1
> ACL Data RX: Handle 65 flags 0x02 dlen 7                 #50 [hci0] 11.833674
      ATT: Read Request (0x0a) len 2
        Handle: 0x0236
< ACL Data TX: Handle 65 flags 0x00 dlen 7                 #51 [hci0] 11.840770
      ATT: Read Response (0x0b) len 2
        Value: 0663
> HCI Event: Number of Completed Packets (0x13) plen 5     #52 [hci0] 12.078687
        Num handles: 1
        Handle: 65
        Count: 1
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #53 [hci0] 14.055212
      ATT: Write Request (0x12) len 4
        Handle: 0x0237
          Data: 0100
< ACL Data TX: Handle 65 flags 0x00 dlen 5                 #54 [hci0] 14.056230
      ATT: Write Response (0x13) len 0
> HCI Event: Number of Completed Packets (0x13) plen 5     #55 [hci0] 14.329045
        Num handles: 1
        Handle: 65
        Count: 1
< ACL Data TX: Handle 65 flags 0x00 dlen 11                #56 [hci0] 15.078671
      ATT: Handle Value Notification (0x1b) len 6
        Handle: 0x0236
          Data: 0e750000
> HCI Event: Number of Completed Packets (0x13) plen 5     #57 [hci0] 15.330353
        Num handles: 1
        Handle: 65
        Count: 1
< ACL Data TX: Handle 65 flags 0x00 dlen 9                 #58 [hci0] 16.071839
      ATT: Handle Value Notification (0x1b) len 4
        Handle: 0x0236
          Data: 066e
> ACL Data RX: H

On Mon, Jan 25, 2021 at 9:59 AM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Hi Kenny,
>
> On Sun, Jan 24, 2021 at 10:42 PM Kenny Bian <kennybian@gmail.com> wrote:
> >
> > Hi Luiz,
> >
> > Thank you so much for your reply. I appreciate it.
> >
> > By "registering the services", do you mean "RegisterApplication()" in
> > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server#n656?
> > If that is the case, I believe I already registered the services.
> > I checked the files in /var/lib/bluetooth. According to
> > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/settings-storage.txt#n321,
> > there should be a "[ServiceChanged]" section in the "info" file. But I
> > don't see it in the "info" file. Is there a way to tell the "Service
> > Changed Indication" is actually working?
> > Let's suppose the "Service Changed Indication" is already enabled, is
> > there a way for the mobile app to check on their side to tell which
> > service(s) got changed?
>
> HCI traces (btmon) should be able to tell you if it has been
> subscribed or not, if there is an Indication in it it probably means
> the remote has subscribed.
>
> > Thanks again for your help.
> >
> > On Sun, Jan 24, 2021 at 7:35 PM Luiz Augusto von Dentz
> > <luiz.dentz@gmail.com> wrote:
> > >
> > > Hi Kenny,
> > >
> > > On Sun, Jan 24, 2021 at 12:45 AM Kenny Bian <kennybian@gmail.com> wrote:
> > > >
> > > > Hello,
> > > >
> > > > We implemented a GATT server on Linux in Python. The code is based on
> > > > the code sample(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> > > > The BlueZ version is 5.48. But we found a problem. The cached data in
> > > > /var/lib/bluetooth caused the mobile app to crash if some
> > > > characteristics are changed. After some research, we found "Under BLE
> > > > standard 'Generic Attribute'(0x1801), there is a Characteristic
> > > > 'Service Changed' (0x2A05) with 'indicate' property", see
> > > > https://github.com/espressif/esp-idf/issues/1777.
> > > >
> > > > The questions we have:
> > > > How to enable the "Service Changed Indication"(0x2A05) in the
> > > > bluetooth? Is there any code example in Python?
> > >
> > > If you are registering the services with Bluetoothd then it should
> > > generate the service change automatically:
> > >
> > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1185
> > >
> > > When a new service is registered it is indicated here:
> > >
> > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1452
> > >
> > >
> > > --
> > > Luiz Augusto von Dentz
>
>
>
> --
> Luiz Augusto von Dentz

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

* Re: How to add "Service Changed Indication"
  2021-01-27  8:42       ` Kenny Bian
@ 2021-01-27  8:46         ` Kenny Bian
  2021-01-27  8:50           ` Kenny Bian
  0 siblings, 1 reply; 8+ messages in thread
From: Kenny Bian @ 2021-01-27  8:46 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

Hi Luiz,

On Wed, Jan 27, 2021 at 12:42 AM Kenny Bian <kennybian@gmail.com> wrote:
>
> Hi Luiz,
>
> Thank you so much for your information.
>
> I created a test GATT server from the sample
> code(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> I have 2 python scripts. In the "bt_read.py" I created, the Heart Rate
> Measurement(2A37) and Body Sensor Location(2A38) only have Read
> attribute. In the "bt_notify.py" I created, the Heart Rate
> Measurement(2A37) and Body Sensor Location(2A38) only have both the
> Read and Notify attribute.
>
> Here is what I did:
> I ran the "bt_read.py" and captured the btmon log. Then I ran
> "bt_notify.py" and captured the btmon log. I read both logs. But I
> don't see there is any info regarding the "Service Changed
> Indication".
>
> Here is the btmon log with both the Read and Notify attributes below.
> Thanks again for your help!
> =========================================================================
> Bluetooth monitor ver 5.48
> = Note: Linux version 4.19.35-g92e18fefc77 (armv7l)                    0.809169
> = Note: Bluetooth subsystem version 2.22                               0.809182
> = New Index: 00:16:A4:4A:2D:27 (Primary,UART,hci0)              [hci0] 0.809187
> = Open Index: 00:16:A4:4A:2D:27                                 [hci0] 0.809190
> = Index Info: 00:16:A4:4.. (Cypress Semiconductor Corporation)  [hci0] 0.809194
> @ MGMT Open: bluetoothd (privileged) version 1.14             {0x0002} 0.809200
> @ MGMT Open: bluetoothd (privileged) version 1.14             {0x0001} 0.809203
> @ MGMT Open: btmon (privileged) version 1.14                  {0x0003} 0.809276
> > ACL Data RX: Handle 65 flags 0x02 dlen 8                   #1 [hci0] 4.543721
>       ATT: Handle Value Notification (0x1b) len 3
>         Handle: 0x0016
>           Data: 64
> > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #2 [hci0] 6.883753
>       ATT: Read By Group Type Request (0x10) len 6
>         Handle range: 0x0001-0xffff
>         Attribute group type: Primary Service (0x2800)
> < ACL Data TX: Handle 65 flags 0x00 dlen 30                  #3 [hci0] 6.884412
>       ATT: Read By Group Type Response (0x11) len 25
>         Attribute data length: 6
>         Attribute group list: 4 entries
>         Handle range: 0x0001-0x0005
>         UUID: Generic Access Profile (0x1800)
>         Handle range: 0x0006-0x0009
>         UUID: Generic Attribute Profile (0x1801)
>         Handle range: 0x0234-0x023c
>         UUID: Heart Rate (0x180d)
>         Handle range: 0x023d-0x0240
>         UUID: Battery Service (0x180f)
> > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #4 [hci0] 6.944638
>       ATT: Read By Group Type Request (0x10) len 6
>         Handle range: 0x0241-0xffff
>         Attribute group type: Primary Service (0x2800)
> < ACL Data TX: Handle 65 flags 0x00 dlen 26                  #5 [hci0] 6.945293
>       ATT: Read By Group Type Response (0x11) len 21
>         Attribute data length: 20
>         Attribute group list: 1 entry
>         Handle range: 0x0241-0x0250
>         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef0)
> > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #6 [hci0] 7.004723
>       ATT: Read By Group Type Request (0x10) len 6
>         Handle range: 0x0251-0xffff
>         Attribute group type: Primary Service (0x2800)
> < ACL Data TX: Handle 65 flags 0x00 dlen 9                   #7 [hci0] 7.005369
>       ATT: Error Response (0x01) len 4
>         Read By Group Type Request (0x10)
>         Handle: 0x0251
>         Error: Attribute Not Found (0x0a)
> > HCI Event: Number of Completed Packets (0x13) plen 5       #8 [hci0] 7.005549
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #9 [hci0] 7.064450
>       ATT: Read By Type Request (0x08) len 6
>         Handle range: 0x0234-0x023c
>         Attribute type: Characteristic (0x2803)
> < ACL Data TX: Handle 65 flags 0x00 dlen 27                 #10 [hci0] 7.065112
>       ATT: Read By Type Response (0x09) len 22
>         Attribute data length: 7
>         Attribute data list: 3 entries
>         Handle: 0x0235
>         Value: 123602372a
>         Handle: 0x0238
>         Value: 123902382a
>         Handle: 0x023b
>         Value: 083c02392a
> > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #11 [hci0] 7.124428
>       ATT: Read By Type Request (0x08) len 6
>         Handle range: 0x023d-0x0240
>         Attribute type: Characteristic (0x2803)
> < ACL Data TX: Handle 65 flags 0x00 dlen 13                 #12 [hci0] 7.125226
>       ATT: Read By Type Response (0x09) len 8
>         Attribute data length: 7
>         Attribute data list: 1 entry
>         Handle: 0x023e
>         Value: 123f02192a
> > HCI Event: Number of Completed Packets (0x13) plen 5      #13 [hci0] 7.125376
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #14 [hci0] 7.184416
>       ATT: Read By Type Request (0x08) len 6
>         Handle range: 0x0241-0x0250
>         Attribute type: Characteristic (0x2803)
> < ACL Data TX: Handle 65 flags 0x00 dlen 69                 #15 [hci0] 7.185101
>       ATT: Read By Type Response (0x09) len 64
>         Attribute data length: 21
>         Attribute data list: 3 entries
>         Handle: 0x0242
>         Value: 8a4302f1debc9a785634127856341278563412
>         Handle: 0x0247
>         Value: 8a4802f3debc9a785634127856341278563412
>         Handle: 0x024c
>         Value: 8a4d02f5debc9a785634127856341278563412
> > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #16 [hci0] 7.244526
>       ATT: Read By Type Request (0x08) len 6
>         Handle range: 0x024e-0x0250
>         Attribute type: Characteristic (0x2803)
> < ACL Data TX: Handle 65 flags 0x00 dlen 9                  #17 [hci0] 7.246144
>       ATT: Error Response (0x01) len 4
>         Read By Type Request (0x08)
>         Handle: 0x024e
>         Error: Attribute Not Found (0x0a)
> > HCI Event: Number of Completed Packets (0x13) plen 5      #18 [hci0] 7.246564
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #19 [hci0] 7.304500
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x0237-0x0237
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #20 [hci0] 7.305951
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x0237
>         UUID: Client Characteristic Configuration (0x2902)
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #21 [hci0] 7.364540
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x023a-0x023a
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #22 [hci0] 7.366242
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x023a
>         UUID: Client Characteristic Configuration (0x2902)
> > HCI Event: Number of Completed Packets (0x13) plen 5      #23 [hci0] 7.366660
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #24 [hci0] 7.424617
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x0240-0x0240
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #25 [hci0] 7.426085
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x0240
>         UUID: Client Characteristic Configuration (0x2902)
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #26 [hci0] 7.484523
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x0244-0x0246
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #27 [hci0] 7.486104
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x0244
>         UUID: Characteristic Extended Properties (0x2900)
> > HCI Event: Number of Completed Packets (0x13) plen 5      #28 [hci0] 7.486520
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #29 [hci0] 7.544546
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x0245-0x0246
> < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #30 [hci0] 7.546011
>       ATT: Find Information Response (0x05) len 19
>         Format: UUID-128 (0x02)
>         Handle: 0x0245
>         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef2)
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #31 [hci0] 7.604713
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x0246-0x0246
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #32 [hci0] 7.606323
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x0246
>         UUID: Characteristic User Description (0x2901)
> > HCI Event: Number of Completed Packets (0x13) plen 5      #33 [hci0] 7.606747
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #34 [hci0] 7.664243
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x0249-0x024b
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #35 [hci0] 7.665862
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x0249
>         UUID: Characteristic Extended Properties (0x2900)
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #36 [hci0] 7.724603
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x024a-0x024b
> < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #37 [hci0] 7.726315
>       ATT: Find Information Response (0x05) len 19
>         Format: UUID-128 (0x02)
>         Handle: 0x024a
>         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef4)
> > HCI Event: Number of Completed Packets (0x13) plen 5      #38 [hci0] 7.726625
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #39 [hci0] 7.784545
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x024b-0x024b
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #40 [hci0] 7.785996
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x024b
>         UUID: Characteristic User Description (0x2901)
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #41 [hci0] 7.844187
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x024e-0x0250
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #42 [hci0] 7.845777
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x024e
>         UUID: Characteristic Extended Properties (0x2900)
> > HCI Event: Number of Completed Packets (0x13) plen 5      #43 [hci0] 7.846215
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #44 [hci0] 7.904466
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x024f-0x0250
> < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #45 [hci0] 7.906160
>       ATT: Find Information Response (0x05) len 19
>         Format: UUID-128 (0x02)
>         Handle: 0x024f
>         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef6)
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #46 [hci0] 7.964493
>       ATT: Find Information Request (0x04) len 4
>         Handle range: 0x0250-0x0250
> < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #47 [hci0] 7.966067
>       ATT: Find Information Response (0x05) len 5
>         Format: UUID-16 (0x01)
>         Handle: 0x0250
>         UUID: Characteristic User Description (0x2901)
> > HCI Event: Number of Completed Packets (0x13) plen 5      #48 [hci0] 7.966489
>         Num handles: 1
>         Handle: 65
>         Count: 2
> > HCI Event: Number of Completed Packets (0x13) plen 5      #49 [hci0] 8.203559
>         Num handles: 1
>         Handle: 65
>         Count: 1
> > ACL Data RX: Handle 65 flags 0x02 dlen 7                 #50 [hci0] 11.833674
>       ATT: Read Request (0x0a) len 2
>         Handle: 0x0236
> < ACL Data TX: Handle 65 flags 0x00 dlen 7                 #51 [hci0] 11.840770
>       ATT: Read Response (0x0b) len 2
>         Value: 0663
> > HCI Event: Number of Completed Packets (0x13) plen 5     #52 [hci0] 12.078687
>         Num handles: 1
>         Handle: 65
>         Count: 1
> > ACL Data RX: Handle 65 flags 0x02 dlen 9                 #53 [hci0] 14.055212
>       ATT: Write Request (0x12) len 4
>         Handle: 0x0237
>           Data: 0100
> < ACL Data TX: Handle 65 flags 0x00 dlen 5                 #54 [hci0] 14.056230
>       ATT: Write Response (0x13) len 0
> > HCI Event: Number of Completed Packets (0x13) plen 5     #55 [hci0] 14.329045
>         Num handles: 1
>         Handle: 65
>         Count: 1
> < ACL Data TX: Handle 65 flags 0x00 dlen 11                #56 [hci0] 15.078671
>       ATT: Handle Value Notification (0x1b) len 6
>         Handle: 0x0236
>           Data: 0e750000
> > HCI Event: Number of Completed Packets (0x13) plen 5     #57 [hci0] 15.330353
>         Num handles: 1
>         Handle: 65
>         Count: 1
> < ACL Data TX: Handle 65 flags 0x00 dlen 9                 #58 [hci0] 16.071839
>       ATT: Handle Value Notification (0x1b) len 4
>         Handle: 0x0236
>           Data: 066e
> > ACL Data RX: H
>
> On Mon, Jan 25, 2021 at 9:59 AM Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> >
> > Hi Kenny,
> >
> > On Sun, Jan 24, 2021 at 10:42 PM Kenny Bian <kennybian@gmail.com> wrote:
> > >
> > > Hi Luiz,
> > >
> > > Thank you so much for your reply. I appreciate it.
> > >
> > > By "registering the services", do you mean "RegisterApplication()" in
> > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server#n656?
> > > If that is the case, I believe I already registered the services.
> > > I checked the files in /var/lib/bluetooth. According to
> > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/settings-storage.txt#n321,
> > > there should be a "[ServiceChanged]" section in the "info" file. But I
> > > don't see it in the "info" file. Is there a way to tell the "Service
> > > Changed Indication" is actually working?
> > > Let's suppose the "Service Changed Indication" is already enabled, is
> > > there a way for the mobile app to check on their side to tell which
> > > service(s) got changed?
> >
> > HCI traces (btmon) should be able to tell you if it has been
> > subscribed or not, if there is an Indication in it it probably means
> > the remote has subscribed.
> >
> > > Thanks again for your help.
> > >
> > > On Sun, Jan 24, 2021 at 7:35 PM Luiz Augusto von Dentz
> > > <luiz.dentz@gmail.com> wrote:
> > > >
> > > > Hi Kenny,
> > > >
> > > > On Sun, Jan 24, 2021 at 12:45 AM Kenny Bian <kennybian@gmail.com> wrote:
> > > > >
> > > > > Hello,
> > > > >
> > > > > We implemented a GATT server on Linux in Python. The code is based on
> > > > > the code sample(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> > > > > The BlueZ version is 5.48. But we found a problem. The cached data in
> > > > > /var/lib/bluetooth caused the mobile app to crash if some
> > > > > characteristics are changed. After some research, we found "Under BLE
> > > > > standard 'Generic Attribute'(0x1801), there is a Characteristic
> > > > > 'Service Changed' (0x2A05) with 'indicate' property", see
> > > > > https://github.com/espressif/esp-idf/issues/1777.
> > > > >
> > > > > The questions we have:
> > > > > How to enable the "Service Changed Indication"(0x2A05) in the
> > > > > bluetooth? Is there any code example in Python?
> > > >
> > > > If you are registering the services with Bluetoothd then it should
> > > > generate the service change automatically:
> > > >
> > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1185
> > > >
> > > > When a new service is registered it is indicated here:
> > > >
> > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1452
> > > >
> > > >
> > > > --
> > > > Luiz Augusto von Dentz
> >
> >
> >
> > --
> > Luiz Augusto von Dentz

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

* Re: How to add "Service Changed Indication"
  2021-01-27  8:46         ` Kenny Bian
@ 2021-01-27  8:50           ` Kenny Bian
  2021-01-28 19:48             ` Kenny Bian
  0 siblings, 1 reply; 8+ messages in thread
From: Kenny Bian @ 2021-01-27  8:50 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

[-- Attachment #1: Type: text/plain, Size: 17997 bytes --]

Hi Luiz,

I'm not sure if I can attach files to this forum. I just try to attach
the files about the "Service Changed Indication" issue.

Here is the list of files:
bt_read.py - the script that the "Heart Rate Measurement" and "Body
Sensor Location" characteristics only have the Read attribute
bt_notify.py - the script that the "Heart Rate Measurement" and "Body
Sensor Location" characteristics only have both the Read and Notify
attributes
btmon_read.log - the btmon log when running bt_read.py
btmon_notify.log - the btmon log when running bt_notify.py

Thank you very much!

On Wed, Jan 27, 2021 at 12:46 AM Kenny Bian <kennybian@gmail.com> wrote:
>
> Hi Luiz,
>
> On Wed, Jan 27, 2021 at 12:42 AM Kenny Bian <kennybian@gmail.com> wrote:
> >
> > Hi Luiz,
> >
> > Thank you so much for your information.
> >
> > I created a test GATT server from the sample
> > code(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> > I have 2 python scripts. In the "bt_read.py" I created, the Heart Rate
> > Measurement(2A37) and Body Sensor Location(2A38) only have Read
> > attribute. In the "bt_notify.py" I created, the Heart Rate
> > Measurement(2A37) and Body Sensor Location(2A38) only have both the
> > Read and Notify attribute.
> >
> > Here is what I did:
> > I ran the "bt_read.py" and captured the btmon log. Then I ran
> > "bt_notify.py" and captured the btmon log. I read both logs. But I
> > don't see there is any info regarding the "Service Changed
> > Indication".
> >
> > Here is the btmon log with both the Read and Notify attributes below.
> > Thanks again for your help!
> > =========================================================================
> > Bluetooth monitor ver 5.48
> > = Note: Linux version 4.19.35-g92e18fefc77 (armv7l)                    0.809169
> > = Note: Bluetooth subsystem version 2.22                               0.809182
> > = New Index: 00:16:A4:4A:2D:27 (Primary,UART,hci0)              [hci0] 0.809187
> > = Open Index: 00:16:A4:4A:2D:27                                 [hci0] 0.809190
> > = Index Info: 00:16:A4:4.. (Cypress Semiconductor Corporation)  [hci0] 0.809194
> > @ MGMT Open: bluetoothd (privileged) version 1.14             {0x0002} 0.809200
> > @ MGMT Open: bluetoothd (privileged) version 1.14             {0x0001} 0.809203
> > @ MGMT Open: btmon (privileged) version 1.14                  {0x0003} 0.809276
> > > ACL Data RX: Handle 65 flags 0x02 dlen 8                   #1 [hci0] 4.543721
> >       ATT: Handle Value Notification (0x1b) len 3
> >         Handle: 0x0016
> >           Data: 64
> > > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #2 [hci0] 6.883753
> >       ATT: Read By Group Type Request (0x10) len 6
> >         Handle range: 0x0001-0xffff
> >         Attribute group type: Primary Service (0x2800)
> > < ACL Data TX: Handle 65 flags 0x00 dlen 30                  #3 [hci0] 6.884412
> >       ATT: Read By Group Type Response (0x11) len 25
> >         Attribute data length: 6
> >         Attribute group list: 4 entries
> >         Handle range: 0x0001-0x0005
> >         UUID: Generic Access Profile (0x1800)
> >         Handle range: 0x0006-0x0009
> >         UUID: Generic Attribute Profile (0x1801)
> >         Handle range: 0x0234-0x023c
> >         UUID: Heart Rate (0x180d)
> >         Handle range: 0x023d-0x0240
> >         UUID: Battery Service (0x180f)
> > > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #4 [hci0] 6.944638
> >       ATT: Read By Group Type Request (0x10) len 6
> >         Handle range: 0x0241-0xffff
> >         Attribute group type: Primary Service (0x2800)
> > < ACL Data TX: Handle 65 flags 0x00 dlen 26                  #5 [hci0] 6.945293
> >       ATT: Read By Group Type Response (0x11) len 21
> >         Attribute data length: 20
> >         Attribute group list: 1 entry
> >         Handle range: 0x0241-0x0250
> >         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef0)
> > > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #6 [hci0] 7.004723
> >       ATT: Read By Group Type Request (0x10) len 6
> >         Handle range: 0x0251-0xffff
> >         Attribute group type: Primary Service (0x2800)
> > < ACL Data TX: Handle 65 flags 0x00 dlen 9                   #7 [hci0] 7.005369
> >       ATT: Error Response (0x01) len 4
> >         Read By Group Type Request (0x10)
> >         Handle: 0x0251
> >         Error: Attribute Not Found (0x0a)
> > > HCI Event: Number of Completed Packets (0x13) plen 5       #8 [hci0] 7.005549
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #9 [hci0] 7.064450
> >       ATT: Read By Type Request (0x08) len 6
> >         Handle range: 0x0234-0x023c
> >         Attribute type: Characteristic (0x2803)
> > < ACL Data TX: Handle 65 flags 0x00 dlen 27                 #10 [hci0] 7.065112
> >       ATT: Read By Type Response (0x09) len 22
> >         Attribute data length: 7
> >         Attribute data list: 3 entries
> >         Handle: 0x0235
> >         Value: 123602372a
> >         Handle: 0x0238
> >         Value: 123902382a
> >         Handle: 0x023b
> >         Value: 083c02392a
> > > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #11 [hci0] 7.124428
> >       ATT: Read By Type Request (0x08) len 6
> >         Handle range: 0x023d-0x0240
> >         Attribute type: Characteristic (0x2803)
> > < ACL Data TX: Handle 65 flags 0x00 dlen 13                 #12 [hci0] 7.125226
> >       ATT: Read By Type Response (0x09) len 8
> >         Attribute data length: 7
> >         Attribute data list: 1 entry
> >         Handle: 0x023e
> >         Value: 123f02192a
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #13 [hci0] 7.125376
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #14 [hci0] 7.184416
> >       ATT: Read By Type Request (0x08) len 6
> >         Handle range: 0x0241-0x0250
> >         Attribute type: Characteristic (0x2803)
> > < ACL Data TX: Handle 65 flags 0x00 dlen 69                 #15 [hci0] 7.185101
> >       ATT: Read By Type Response (0x09) len 64
> >         Attribute data length: 21
> >         Attribute data list: 3 entries
> >         Handle: 0x0242
> >         Value: 8a4302f1debc9a785634127856341278563412
> >         Handle: 0x0247
> >         Value: 8a4802f3debc9a785634127856341278563412
> >         Handle: 0x024c
> >         Value: 8a4d02f5debc9a785634127856341278563412
> > > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #16 [hci0] 7.244526
> >       ATT: Read By Type Request (0x08) len 6
> >         Handle range: 0x024e-0x0250
> >         Attribute type: Characteristic (0x2803)
> > < ACL Data TX: Handle 65 flags 0x00 dlen 9                  #17 [hci0] 7.246144
> >       ATT: Error Response (0x01) len 4
> >         Read By Type Request (0x08)
> >         Handle: 0x024e
> >         Error: Attribute Not Found (0x0a)
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #18 [hci0] 7.246564
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #19 [hci0] 7.304500
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x0237-0x0237
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #20 [hci0] 7.305951
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x0237
> >         UUID: Client Characteristic Configuration (0x2902)
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #21 [hci0] 7.364540
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x023a-0x023a
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #22 [hci0] 7.366242
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x023a
> >         UUID: Client Characteristic Configuration (0x2902)
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #23 [hci0] 7.366660
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #24 [hci0] 7.424617
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x0240-0x0240
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #25 [hci0] 7.426085
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x0240
> >         UUID: Client Characteristic Configuration (0x2902)
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #26 [hci0] 7.484523
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x0244-0x0246
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #27 [hci0] 7.486104
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x0244
> >         UUID: Characteristic Extended Properties (0x2900)
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #28 [hci0] 7.486520
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #29 [hci0] 7.544546
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x0245-0x0246
> > < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #30 [hci0] 7.546011
> >       ATT: Find Information Response (0x05) len 19
> >         Format: UUID-128 (0x02)
> >         Handle: 0x0245
> >         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef2)
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #31 [hci0] 7.604713
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x0246-0x0246
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #32 [hci0] 7.606323
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x0246
> >         UUID: Characteristic User Description (0x2901)
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #33 [hci0] 7.606747
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #34 [hci0] 7.664243
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x0249-0x024b
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #35 [hci0] 7.665862
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x0249
> >         UUID: Characteristic Extended Properties (0x2900)
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #36 [hci0] 7.724603
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x024a-0x024b
> > < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #37 [hci0] 7.726315
> >       ATT: Find Information Response (0x05) len 19
> >         Format: UUID-128 (0x02)
> >         Handle: 0x024a
> >         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef4)
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #38 [hci0] 7.726625
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #39 [hci0] 7.784545
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x024b-0x024b
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #40 [hci0] 7.785996
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x024b
> >         UUID: Characteristic User Description (0x2901)
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #41 [hci0] 7.844187
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x024e-0x0250
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #42 [hci0] 7.845777
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x024e
> >         UUID: Characteristic Extended Properties (0x2900)
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #43 [hci0] 7.846215
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #44 [hci0] 7.904466
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x024f-0x0250
> > < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #45 [hci0] 7.906160
> >       ATT: Find Information Response (0x05) len 19
> >         Format: UUID-128 (0x02)
> >         Handle: 0x024f
> >         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef6)
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #46 [hci0] 7.964493
> >       ATT: Find Information Request (0x04) len 4
> >         Handle range: 0x0250-0x0250
> > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #47 [hci0] 7.966067
> >       ATT: Find Information Response (0x05) len 5
> >         Format: UUID-16 (0x01)
> >         Handle: 0x0250
> >         UUID: Characteristic User Description (0x2901)
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #48 [hci0] 7.966489
> >         Num handles: 1
> >         Handle: 65
> >         Count: 2
> > > HCI Event: Number of Completed Packets (0x13) plen 5      #49 [hci0] 8.203559
> >         Num handles: 1
> >         Handle: 65
> >         Count: 1
> > > ACL Data RX: Handle 65 flags 0x02 dlen 7                 #50 [hci0] 11.833674
> >       ATT: Read Request (0x0a) len 2
> >         Handle: 0x0236
> > < ACL Data TX: Handle 65 flags 0x00 dlen 7                 #51 [hci0] 11.840770
> >       ATT: Read Response (0x0b) len 2
> >         Value: 0663
> > > HCI Event: Number of Completed Packets (0x13) plen 5     #52 [hci0] 12.078687
> >         Num handles: 1
> >         Handle: 65
> >         Count: 1
> > > ACL Data RX: Handle 65 flags 0x02 dlen 9                 #53 [hci0] 14.055212
> >       ATT: Write Request (0x12) len 4
> >         Handle: 0x0237
> >           Data: 0100
> > < ACL Data TX: Handle 65 flags 0x00 dlen 5                 #54 [hci0] 14.056230
> >       ATT: Write Response (0x13) len 0
> > > HCI Event: Number of Completed Packets (0x13) plen 5     #55 [hci0] 14.329045
> >         Num handles: 1
> >         Handle: 65
> >         Count: 1
> > < ACL Data TX: Handle 65 flags 0x00 dlen 11                #56 [hci0] 15.078671
> >       ATT: Handle Value Notification (0x1b) len 6
> >         Handle: 0x0236
> >           Data: 0e750000
> > > HCI Event: Number of Completed Packets (0x13) plen 5     #57 [hci0] 15.330353
> >         Num handles: 1
> >         Handle: 65
> >         Count: 1
> > < ACL Data TX: Handle 65 flags 0x00 dlen 9                 #58 [hci0] 16.071839
> >       ATT: Handle Value Notification (0x1b) len 4
> >         Handle: 0x0236
> >           Data: 066e
> > > ACL Data RX: H
> >
> > On Mon, Jan 25, 2021 at 9:59 AM Luiz Augusto von Dentz
> > <luiz.dentz@gmail.com> wrote:
> > >
> > > Hi Kenny,
> > >
> > > On Sun, Jan 24, 2021 at 10:42 PM Kenny Bian <kennybian@gmail.com> wrote:
> > > >
> > > > Hi Luiz,
> > > >
> > > > Thank you so much for your reply. I appreciate it.
> > > >
> > > > By "registering the services", do you mean "RegisterApplication()" in
> > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server#n656?
> > > > If that is the case, I believe I already registered the services.
> > > > I checked the files in /var/lib/bluetooth. According to
> > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/settings-storage.txt#n321,
> > > > there should be a "[ServiceChanged]" section in the "info" file. But I
> > > > don't see it in the "info" file. Is there a way to tell the "Service
> > > > Changed Indication" is actually working?
> > > > Let's suppose the "Service Changed Indication" is already enabled, is
> > > > there a way for the mobile app to check on their side to tell which
> > > > service(s) got changed?
> > >
> > > HCI traces (btmon) should be able to tell you if it has been
> > > subscribed or not, if there is an Indication in it it probably means
> > > the remote has subscribed.
> > >
> > > > Thanks again for your help.
> > > >
> > > > On Sun, Jan 24, 2021 at 7:35 PM Luiz Augusto von Dentz
> > > > <luiz.dentz@gmail.com> wrote:
> > > > >
> > > > > Hi Kenny,
> > > > >
> > > > > On Sun, Jan 24, 2021 at 12:45 AM Kenny Bian <kennybian@gmail.com> wrote:
> > > > > >
> > > > > > Hello,
> > > > > >
> > > > > > We implemented a GATT server on Linux in Python. The code is based on
> > > > > > the code sample(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> > > > > > The BlueZ version is 5.48. But we found a problem. The cached data in
> > > > > > /var/lib/bluetooth caused the mobile app to crash if some
> > > > > > characteristics are changed. After some research, we found "Under BLE
> > > > > > standard 'Generic Attribute'(0x1801), there is a Characteristic
> > > > > > 'Service Changed' (0x2A05) with 'indicate' property", see
> > > > > > https://github.com/espressif/esp-idf/issues/1777.
> > > > > >
> > > > > > The questions we have:
> > > > > > How to enable the "Service Changed Indication"(0x2A05) in the
> > > > > > bluetooth? Is there any code example in Python?
> > > > >
> > > > > If you are registering the services with Bluetoothd then it should
> > > > > generate the service change automatically:
> > > > >
> > > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1185
> > > > >
> > > > > When a new service is registered it is indicated here:
> > > > >
> > > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1452
> > > > >
> > > > >
> > > > > --
> > > > > Luiz Augusto von Dentz
> > >
> > >
> > >
> > > --
> > > Luiz Augusto von Dentz

[-- Attachment #2: bt_read.py --]
[-- Type: text/plain, Size: 26595 bytes --]

#!/usr/bin/env python3

import dbus
import dbus.exceptions
import dbus.mainloop.glib
import dbus.service

import array
try:
  from gi.repository import GObject
except ImportError:
  import gobject as GObject
import sys

from random import randint

# Advert
import gobject

mainloop = None

BLUEZ_SERVICE_NAME = 'org.bluez'
GATT_MANAGER_IFACE = 'org.bluez.GattManager1'
DBUS_OM_IFACE =      'org.freedesktop.DBus.ObjectManager'
DBUS_PROP_IFACE =    'org.freedesktop.DBus.Properties'

GATT_SERVICE_IFACE = 'org.bluez.GattService1'
GATT_CHRC_IFACE =    'org.bluez.GattCharacteristic1'
GATT_DESC_IFACE =    'org.bluez.GattDescriptor1'

# Advert
LE_ADVERTISING_MANAGER_IFACE = 'org.bluez.LEAdvertisingManager1'
LE_ADVERTISEMENT_IFACE = 'org.bluez.LEAdvertisement1'

# Advert
class InvalidArgsException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.freedesktop.DBus.Error.InvalidArgs'


class NotSupportedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.NotSupported'


class NotPermittedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.NotPermitted'


class InvalidValueLengthException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.InvalidValueLength'


class FailedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.Failed'


class Advertisement(dbus.service.Object):
    PATH_BASE = '/org/bluez/example/advertisement'

    def __init__(self, bus, index, advertising_type):
        self.path = self.PATH_BASE + str(index)
        self.bus = bus
        self.ad_type = advertising_type
        self.service_uuids = None
        self.manufacturer_data = None
        self.solicit_uuids = None
        self.service_data = None
        self.local_name = None
        self.include_tx_power = None
        self.data = None
        dbus.service.Object.__init__(self, bus, self.path)

    def get_properties(self):
        properties = dict()
        properties['Type'] = self.ad_type
        if self.service_uuids is not None:
            properties['ServiceUUIDs'] = dbus.Array(self.service_uuids,
                                                    signature='s')
        if self.solicit_uuids is not None:
            properties['SolicitUUIDs'] = dbus.Array(self.solicit_uuids,
                                                    signature='s')
        if self.manufacturer_data is not None:
            properties['ManufacturerData'] = dbus.Dictionary(
                self.manufacturer_data, signature='qv')
        if self.service_data is not None:
            properties['ServiceData'] = dbus.Dictionary(self.service_data,
                                                        signature='sv')
        if self.local_name is not None:
            properties['LocalName'] = dbus.String(self.local_name)
        if self.include_tx_power is not None:
            properties['IncludeTxPower'] = dbus.Boolean(self.include_tx_power)

        if self.data is not None:
            properties['Data'] = dbus.Dictionary(
                self.data, signature='yv')
        return {LE_ADVERTISEMENT_IFACE: properties}

    def get_path(self):
        return dbus.ObjectPath(self.path)

    def add_service_uuid(self, uuid):
        if not self.service_uuids:
            self.service_uuids = []
        self.service_uuids.append(uuid)

    def add_solicit_uuid(self, uuid):
        if not self.solicit_uuids:
            self.solicit_uuids = []
        self.solicit_uuids.append(uuid)

    def add_manufacturer_data(self, manuf_code, data):
        if not self.manufacturer_data:
            self.manufacturer_data = dbus.Dictionary({}, signature='qv')
        self.manufacturer_data[manuf_code] = dbus.Array(data, signature='y')

    def add_service_data(self, uuid, data):
        if not self.service_data:
            self.service_data = dbus.Dictionary({}, signature='sv')
        self.service_data[uuid] = dbus.Array(data, signature='y')

    def add_local_name(self, name):
        if not self.local_name:
            self.local_name = ""
        self.local_name = dbus.String(name)

    def add_data(self, ad_type, data):
        if not self.data:
            self.data = dbus.Dictionary({}, signature='yv')
        self.data[ad_type] = dbus.Array(data, signature='y')

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        print( 'GetAll')
        if interface != LE_ADVERTISEMENT_IFACE:
            raise InvalidArgsException()
        print( 'returning props')
        return self.get_properties()[LE_ADVERTISEMENT_IFACE]

    @dbus.service.method(LE_ADVERTISEMENT_IFACE,
                         in_signature='',
                         out_signature='')
    def Release(self):
        print( '%s: Released!' % self.path)

class TestAdvertisement(Advertisement):

    def __init__(self, bus, index):
        Advertisement.__init__(self, bus, index, 'peripheral')
        self.add_service_uuid('180D')
        self.add_service_uuid('180F')
        self.add_manufacturer_data(0xffff, [0x00, 0x01, 0x02, 0x03, 0x04])
        self.add_service_data('9999', [0x00, 0x01, 0x02, 0x03, 0x04])
        self.add_local_name('TestAdvertisement')
        self.include_tx_power = True
        self.add_data(0x26, [0x01, 0x01, 0x00])


def register_ad_cb():
    print( 'Advertisement registered')


def register_ad_error_cb(error):
    print( 'Failed to register advertisement: ' + str(error))
    mainloop.quit()





class InvalidArgsException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.freedesktop.DBus.Error.InvalidArgs'

class NotSupportedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.NotSupported'

class NotPermittedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.NotPermitted'

class InvalidValueLengthException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.InvalidValueLength'

class FailedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.Failed'


class Application(dbus.service.Object):
    """
    org.bluez.GattApplication1 interface implementation
    """
    def __init__(self, bus):
        self.path = '/'
        self.services = []
        dbus.service.Object.__init__(self, bus, self.path)
        self.add_service(HeartRateService(bus, 0))
        self.add_service(BatteryService(bus, 1))
        self.add_service(TestService(bus, 2))

    def get_path(self):
        return dbus.ObjectPath(self.path)

    def add_service(self, service):
        self.services.append(service)

    @dbus.service.method(DBUS_OM_IFACE, out_signature='a{oa{sa{sv}}}')
    def GetManagedObjects(self):
        response = {}
        print('GetManagedObjects')

        for service in self.services:
            response[service.get_path()] = service.get_properties()
            chrcs = service.get_characteristics()
            for chrc in chrcs:
                response[chrc.get_path()] = chrc.get_properties()
                descs = chrc.get_descriptors()
                for desc in descs:
                    response[desc.get_path()] = desc.get_properties()

        return response


class Service(dbus.service.Object):
    """
    org.bluez.GattService1 interface implementation
    """
    PATH_BASE = '/org/bluez/example/service'

    def __init__(self, bus, index, uuid, primary):
        self.path = self.PATH_BASE + str(index)
        self.bus = bus
        self.uuid = uuid
        self.primary = primary
        self.characteristics = []
        dbus.service.Object.__init__(self, bus, self.path)

    def get_properties(self):
        return {
                GATT_SERVICE_IFACE: {
                        'UUID': self.uuid,
                        'Primary': self.primary,
                        'Characteristics': dbus.Array(
                                self.get_characteristic_paths(),
                                signature='o')
                }
        }

    def get_path(self):
        return dbus.ObjectPath(self.path)

    def add_characteristic(self, characteristic):
        self.characteristics.append(characteristic)

    def get_characteristic_paths(self):
        result = []
        for chrc in self.characteristics:
            result.append(chrc.get_path())
        return result

    def get_characteristics(self):
        return self.characteristics

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        if interface != GATT_SERVICE_IFACE:
            raise InvalidArgsException()

        return self.get_properties()[GATT_SERVICE_IFACE]


class Characteristic(dbus.service.Object):
    """
    org.bluez.GattCharacteristic1 interface implementation
    """
    def __init__(self, bus, index, uuid, flags, service):
        self.path = service.path + '/char' + str(index)
        self.bus = bus
        self.uuid = uuid
        self.service = service
        self.flags = flags
        self.descriptors = []
        dbus.service.Object.__init__(self, bus, self.path)

    def get_properties(self):
        return {
                GATT_CHRC_IFACE: {
                        'Service': self.service.get_path(),
                        'UUID': self.uuid,
                        'Flags': self.flags,
                        'Descriptors': dbus.Array(
                                self.get_descriptor_paths(),
                                signature='o')
                }
        }

    def get_path(self):
        return dbus.ObjectPath(self.path)

    def add_descriptor(self, descriptor):
        self.descriptors.append(descriptor)

    def get_descriptor_paths(self):
        result = []
        for desc in self.descriptors:
            result.append(desc.get_path())
        return result

    def get_descriptors(self):
        return self.descriptors

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        if interface != GATT_CHRC_IFACE:
            raise InvalidArgsException()

        return self.get_properties()[GATT_CHRC_IFACE]

    @dbus.service.method(GATT_CHRC_IFACE,
                        in_signature='a{sv}',
                        out_signature='ay')
    def ReadValue(self, options):
        print('Default ReadValue called, returning error')
        raise NotSupportedException()

    @dbus.service.method(GATT_CHRC_IFACE, in_signature='aya{sv}')
    def WriteValue(self, value, options):
        print('Default WriteValue called, returning error')
        raise NotSupportedException()

    @dbus.service.method(GATT_CHRC_IFACE)
    def StartNotify(self):
        print('Default StartNotify called, returning error')
        raise NotSupportedException()

    @dbus.service.method(GATT_CHRC_IFACE)
    def StopNotify(self):
        print('Default StopNotify called, returning error')
        raise NotSupportedException()

    @dbus.service.signal(DBUS_PROP_IFACE,
                         signature='sa{sv}as')
    def PropertiesChanged(self, interface, changed, invalidated):
        pass


class Descriptor(dbus.service.Object):
    """
    org.bluez.GattDescriptor1 interface implementation
    """
    def __init__(self, bus, index, uuid, flags, characteristic):
        self.path = characteristic.path + '/desc' + str(index)
        self.bus = bus
        self.uuid = uuid
        self.flags = flags
        self.chrc = characteristic
        dbus.service.Object.__init__(self, bus, self.path)

    def get_properties(self):
        return {
                GATT_DESC_IFACE: {
                        'Characteristic': self.chrc.get_path(),
                        'UUID': self.uuid,
                        'Flags': self.flags,
                }
        }

    def get_path(self):
        return dbus.ObjectPath(self.path)

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        if interface != GATT_DESC_IFACE:
            raise InvalidArgsException()

        return self.get_properties()[GATT_DESC_IFACE]

    @dbus.service.method(GATT_DESC_IFACE,
                        in_signature='a{sv}',
                        out_signature='ay')
    def ReadValue(self, options):
        print ('Default ReadValue called, returning error')
        raise NotSupportedException()

    @dbus.service.method(GATT_DESC_IFACE, in_signature='aya{sv}')
    def WriteValue(self, value, options):
        print('Default WriteValue called, returning error')
        raise NotSupportedException()


class HeartRateService(Service):
    """
    Fake Heart Rate Service that simulates a fake heart beat and control point
    behavior.

    """
    HR_UUID = '0000180d-0000-1000-8000-00805f9b34fb'

    def __init__(self, bus, index):
        Service.__init__(self, bus, index, self.HR_UUID, True)
        self.add_characteristic(HeartRateMeasurementChrc(bus, 0, self))
        self.add_characteristic(BodySensorLocationChrc(bus, 1, self))
        self.add_characteristic(HeartRateControlPointChrc(bus, 2, self))
        self.energy_expended = 0


class HeartRateMeasurementChrc(Characteristic):
    HR_MSRMT_UUID = '00002a37-0000-1000-8000-00805f9b34fb'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.HR_MSRMT_UUID,
                ['read'],
                service)
        self.notifying = False
        self.hr_ee_count = 0
        

    def ReadValue(self, options):
        print('HeartRateMeasurementChrc Read')
        return [dbus.Byte(6), dbus.Byte(99)]


    def hr_msrmt_cb(self):
        value = []
        value.append(dbus.Byte(0x06))

        value.append(dbus.Byte(randint(90, 130)))

        if self.hr_ee_count % 10 == 0:
            value[0] = dbus.Byte(value[0] | 0x08)
            value.append(dbus.Byte(self.service.energy_expended & 0xff))
            value.append(dbus.Byte((self.service.energy_expended >> 8) & 0xff))

        self.service.energy_expended = \
                min(0xffff, self.service.energy_expended + 1)
        self.hr_ee_count += 1

        print('Updating value: ' + repr(value))

        self.PropertiesChanged(GATT_CHRC_IFACE, { 'Value': value }, [])

        return self.notifying

    def _update_hr_msrmt_simulation(self):
        print('Update HR Measurement Simulation')

        if not self.notifying:
            return

        GObject.timeout_add(1000, self.hr_msrmt_cb)

    def StartNotify(self):
        if self.notifying:
            print('Already notifying, nothing to do')
            return

        self.notifying = True
        self._update_hr_msrmt_simulation()

    def StopNotify(self):
        if not self.notifying:
            print('Not notifying, nothing to do')
            return

        self.notifying = False
        self._update_hr_msrmt_simulation()


class BodySensorLocationChrc(Characteristic):
    BODY_SNSR_LOC_UUID = '00002a38-0000-1000-8000-00805f9b34fb'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.BODY_SNSR_LOC_UUID,
                ['read'],
                service)
        self.notifying = False
        self.value = [0x01]

    def ReadValue(self, options):
        # Return 'Chest' as the sensor location.
        return [ 0x02 ]


    def _cb(self):
        value = []

        value.append(dbus.Byte(randint(1, 3)))

        print('Updating value: ' + repr(value))

        self.PropertiesChanged(GATT_CHRC_IFACE, { 'Value': value }, [])

        return self.notifying

    def _update_simulation(self):
        print('Update Simulation')

        if not self.notifying:
            return

        GObject.timeout_add(1000, self._cb)

    def StartNotify(self):
        if self.notifying:
            print('Already notifying, nothing to do')
            return

        self.notifying = True
        self._update_simulation()

    def StopNotify(self):
        if not self.notifying:
            print('Not notifying, nothing to do')
            return

        self.notifying = False
        self._update_simulation()


class HeartRateControlPointChrc(Characteristic):
    HR_CTRL_PT_UUID = '00002a39-0000-1000-8000-00805f9b34fb'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.HR_CTRL_PT_UUID,
                ['write'],
                service)

    def WriteValue(self, value, options):
        print('Heart Rate Control Point WriteValue called')

        if len(value) != 1:
            raise InvalidValueLengthException()

        byte = value[0]
        print('Control Point value: ' + repr(byte))

        if byte != 1:
            raise FailedException("0x80")

        print('Energy Expended field reset!')
        self.service.energy_expended = 0


class BatteryService(Service):
    """
    Fake Battery service that emulates a draining battery.

    """
    BATTERY_UUID = '180f'

    def __init__(self, bus, index):
        Service.__init__(self, bus, index, self.BATTERY_UUID, True)
        self.add_characteristic(BatteryLevelCharacteristic(bus, 0, self))


class BatteryLevelCharacteristic(Characteristic):
    """
    Fake Battery Level characteristic. The battery level is drained by 2 points
    every 5 seconds.

    """
    BATTERY_LVL_UUID = '2a19'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.BATTERY_LVL_UUID,
                ['read', 'notify'],
                service)
        self.notifying = False
        self.battery_lvl = 100
        GObject.timeout_add(5000, self.drain_battery)

    def notify_battery_level(self):
        if not self.notifying:
            return
        self.PropertiesChanged(
                GATT_CHRC_IFACE,
                { 'Value': [dbus.Byte(self.battery_lvl)] }, [])

    def drain_battery(self):
        if not self.notifying:
            return True
        if self.battery_lvl > 0:
            self.battery_lvl -= 2
            if self.battery_lvl < 0:
                self.battery_lvl = 0
        print('Battery Level drained: ' + repr(self.battery_lvl))
        self.notify_battery_level()
        return True

    def ReadValue(self, options):
        print('Battery Level read: ' + repr(self.battery_lvl))
        return [dbus.Byte(self.battery_lvl)]

    def StartNotify(self):
        if self.notifying:
            print('Already notifying, nothing to do')
            return

        self.notifying = True
        self.notify_battery_level()

    def StopNotify(self):
        if not self.notifying:
            print('Not notifying, nothing to do')
            return

        self.notifying = False


class TestService(Service):
    """
    Dummy test service that provides characteristics and descriptors that
    exercise various API functionality.

    """
    TEST_SVC_UUID = '12345678-1234-5678-1234-56789abcdef0'

    def __init__(self, bus, index):
        Service.__init__(self, bus, index, self.TEST_SVC_UUID, True)
        self.add_characteristic(TestCharacteristic(bus, 0, self))
        self.add_characteristic(TestEncryptCharacteristic(bus, 1, self))
        self.add_characteristic(TestSecureCharacteristic(bus, 2, self))

class TestCharacteristic(Characteristic):
    """
    Dummy test characteristic. Allows writing arbitrary bytes to its value, and
    contains "extended properties", as well as a test descriptor.

    """
    TEST_CHRC_UUID = '12345678-1234-5678-1234-56789abcdef1'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.TEST_CHRC_UUID,
                ['read', 'write', 'writable-auxiliaries'],
                service)
        self.value = []
        self.add_descriptor(TestDescriptor(bus, 0, self))
        self.add_descriptor(
                CharacteristicUserDescriptionDescriptor(bus, 1, self))

    def ReadValue(self, options):
        print('TestCharacteristic Read: ' + repr(self.value))
        return self.value

    def WriteValue(self, value, options):
        print('TestCharacteristic Write: ' + repr(value))
        self.value = value


class TestDescriptor(Descriptor):
    """
    Dummy test descriptor. Returns a static value.

    """
    TEST_DESC_UUID = '12345678-1234-5678-1234-56789abcdef2'

    def __init__(self, bus, index, characteristic):
        Descriptor.__init__(
                self, bus, index,
                self.TEST_DESC_UUID,
                ['read', 'write'],
                characteristic)

    def ReadValue(self, options):
        return [
                dbus.Byte('T'), dbus.Byte('e'), dbus.Byte('s'), dbus.Byte('t')
        ]


class CharacteristicUserDescriptionDescriptor(Descriptor):
    """
    Writable CUD descriptor.

    """
    CUD_UUID = '2901'

    def __init__(self, bus, index, characteristic):
        self.writable = 'writable-auxiliaries' in characteristic.flags
        self.value = array.array('B', b'This is a characteristic for testing')
        self.value = self.value.tolist()
        Descriptor.__init__(
                self, bus, index,
                self.CUD_UUID,
                ['read', 'write'],
                characteristic)

    def ReadValue(self, options):
        return self.value

    def WriteValue(self, value, options):
        if not self.writable:
            raise NotPermittedException()
        self.value = value

class TestEncryptCharacteristic(Characteristic):
    """
    Dummy test characteristic requiring encryption.

    """
    TEST_CHRC_UUID = '12345678-1234-5678-1234-56789abcdef3'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.TEST_CHRC_UUID,
                ['encrypt-read', 'encrypt-write'],
                service)
        self.value = []
        self.add_descriptor(TestEncryptDescriptor(bus, 2, self))
        self.add_descriptor(
                CharacteristicUserDescriptionDescriptor(bus, 3, self))

    def ReadValue(self, options):
        print('TestEncryptCharacteristic Read: ' + repr(self.value))
        return self.value

    def WriteValue(self, value, options):
        print('TestEncryptCharacteristic Write: ' + repr(value))
        self.value = value

class TestEncryptDescriptor(Descriptor):
    """
    Dummy test descriptor requiring encryption. Returns a static value.

    """
    TEST_DESC_UUID = '12345678-1234-5678-1234-56789abcdef4'

    def __init__(self, bus, index, characteristic):
        Descriptor.__init__(
                self, bus, index,
                self.TEST_DESC_UUID,
                ['encrypt-read', 'encrypt-write'],
                characteristic)

    def ReadValue(self, options):
        return [
                dbus.Byte('T'), dbus.Byte('e'), dbus.Byte('s'), dbus.Byte('t')
        ]


class TestSecureCharacteristic(Characteristic):
    """
    Dummy test characteristic requiring secure connection.

    """
    TEST_CHRC_UUID = '12345678-1234-5678-1234-56789abcdef5'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.TEST_CHRC_UUID,
                ['secure-read', 'secure-write'],
                service)
        self.value = []
        self.add_descriptor(TestSecureDescriptor(bus, 2, self))
        self.add_descriptor(
                CharacteristicUserDescriptionDescriptor(bus, 3, self))

    def ReadValue(self, options):
        print('TestSecureCharacteristic Read: ' + repr(self.value))
        return self.value

    def WriteValue(self, value, options):
        print('TestSecureCharacteristic Write: ' + repr(value))
        self.value = value


class TestSecureDescriptor(Descriptor):
    """
    Dummy test descriptor requiring secure connection. Returns a static value.

    """
    TEST_DESC_UUID = '12345678-1234-5678-1234-56789abcdef6'

    def __init__(self, bus, index, characteristic):
        Descriptor.__init__(
                self, bus, index,
                self.TEST_DESC_UUID,
                ['secure-read', 'secure-write'],
                characteristic)

    def ReadValue(self, options):
        return [
                dbus.Byte('T'), dbus.Byte('e'), dbus.Byte('s'), dbus.Byte('t')
        ]

def register_app_cb():
    print('GATT application registered')


def register_app_error_cb(error):
    print('Failed to register application: ' + str(error))
    mainloop.quit()


def find_adapter(bus):
    remote_om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'),
                               DBUS_OM_IFACE)
    objects = remote_om.GetManagedObjects()

    for o, props in objects.items():
        if GATT_MANAGER_IFACE in props.keys():
            return o

    return None

def main():
    global mainloop

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()

    adapter = find_adapter(bus)
    if not adapter:
        print('GattManager1 interface not found')
        return

    service_manager = dbus.Interface(
            bus.get_object(BLUEZ_SERVICE_NAME, adapter),
            GATT_MANAGER_IFACE)

    app = Application(bus)

    mainloop = GObject.MainLoop()

    print('Registering GATT application...')

    service_manager.RegisterApplication(app.get_path(), {},
                                    reply_handler=register_app_cb,
                                    error_handler=register_app_error_cb)


    # Advert
    if not adapter:
        print( 'LEAdvertisingManager1 interface not found')
        return

    adapter_props = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter),
                                   "org.freedesktop.DBus.Properties");

    adapter_props.Set("org.bluez.Adapter1", "Powered", dbus.Boolean(1))

    ad_manager = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter),
                                LE_ADVERTISING_MANAGER_IFACE)

    test_advertisement = TestAdvertisement(bus, 0)

    ad_manager.RegisterAdvertisement(test_advertisement.get_path(), {},
                                     reply_handler=register_ad_cb,
                                     error_handler=register_ad_error_cb)

    mainloop.run()

if __name__ == '__main__':
    main()


[-- Attachment #3: bt_notify.py --]
[-- Type: text/plain, Size: 26615 bytes --]

#!/usr/bin/env python3

import dbus
import dbus.exceptions
import dbus.mainloop.glib
import dbus.service

import array
try:
  from gi.repository import GObject
except ImportError:
  import gobject as GObject
import sys

from random import randint

# Advert
import gobject

mainloop = None

BLUEZ_SERVICE_NAME = 'org.bluez'
GATT_MANAGER_IFACE = 'org.bluez.GattManager1'
DBUS_OM_IFACE =      'org.freedesktop.DBus.ObjectManager'
DBUS_PROP_IFACE =    'org.freedesktop.DBus.Properties'

GATT_SERVICE_IFACE = 'org.bluez.GattService1'
GATT_CHRC_IFACE =    'org.bluez.GattCharacteristic1'
GATT_DESC_IFACE =    'org.bluez.GattDescriptor1'

# Advert
LE_ADVERTISING_MANAGER_IFACE = 'org.bluez.LEAdvertisingManager1'
LE_ADVERTISEMENT_IFACE = 'org.bluez.LEAdvertisement1'

# Advert
class InvalidArgsException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.freedesktop.DBus.Error.InvalidArgs'


class NotSupportedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.NotSupported'


class NotPermittedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.NotPermitted'


class InvalidValueLengthException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.InvalidValueLength'


class FailedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.Failed'


class Advertisement(dbus.service.Object):
    PATH_BASE = '/org/bluez/example/advertisement'

    def __init__(self, bus, index, advertising_type):
        self.path = self.PATH_BASE + str(index)
        self.bus = bus
        self.ad_type = advertising_type
        self.service_uuids = None
        self.manufacturer_data = None
        self.solicit_uuids = None
        self.service_data = None
        self.local_name = None
        self.include_tx_power = None
        self.data = None
        dbus.service.Object.__init__(self, bus, self.path)

    def get_properties(self):
        properties = dict()
        properties['Type'] = self.ad_type
        if self.service_uuids is not None:
            properties['ServiceUUIDs'] = dbus.Array(self.service_uuids,
                                                    signature='s')
        if self.solicit_uuids is not None:
            properties['SolicitUUIDs'] = dbus.Array(self.solicit_uuids,
                                                    signature='s')
        if self.manufacturer_data is not None:
            properties['ManufacturerData'] = dbus.Dictionary(
                self.manufacturer_data, signature='qv')
        if self.service_data is not None:
            properties['ServiceData'] = dbus.Dictionary(self.service_data,
                                                        signature='sv')
        if self.local_name is not None:
            properties['LocalName'] = dbus.String(self.local_name)
        if self.include_tx_power is not None:
            properties['IncludeTxPower'] = dbus.Boolean(self.include_tx_power)

        if self.data is not None:
            properties['Data'] = dbus.Dictionary(
                self.data, signature='yv')
        return {LE_ADVERTISEMENT_IFACE: properties}

    def get_path(self):
        return dbus.ObjectPath(self.path)

    def add_service_uuid(self, uuid):
        if not self.service_uuids:
            self.service_uuids = []
        self.service_uuids.append(uuid)

    def add_solicit_uuid(self, uuid):
        if not self.solicit_uuids:
            self.solicit_uuids = []
        self.solicit_uuids.append(uuid)

    def add_manufacturer_data(self, manuf_code, data):
        if not self.manufacturer_data:
            self.manufacturer_data = dbus.Dictionary({}, signature='qv')
        self.manufacturer_data[manuf_code] = dbus.Array(data, signature='y')

    def add_service_data(self, uuid, data):
        if not self.service_data:
            self.service_data = dbus.Dictionary({}, signature='sv')
        self.service_data[uuid] = dbus.Array(data, signature='y')

    def add_local_name(self, name):
        if not self.local_name:
            self.local_name = ""
        self.local_name = dbus.String(name)

    def add_data(self, ad_type, data):
        if not self.data:
            self.data = dbus.Dictionary({}, signature='yv')
        self.data[ad_type] = dbus.Array(data, signature='y')

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        print( 'GetAll')
        if interface != LE_ADVERTISEMENT_IFACE:
            raise InvalidArgsException()
        print( 'returning props')
        return self.get_properties()[LE_ADVERTISEMENT_IFACE]

    @dbus.service.method(LE_ADVERTISEMENT_IFACE,
                         in_signature='',
                         out_signature='')
    def Release(self):
        print( '%s: Released!' % self.path)

class TestAdvertisement(Advertisement):

    def __init__(self, bus, index):
        Advertisement.__init__(self, bus, index, 'peripheral')
        self.add_service_uuid('180D')
        self.add_service_uuid('180F')
        self.add_manufacturer_data(0xffff, [0x00, 0x01, 0x02, 0x03, 0x04])
        self.add_service_data('9999', [0x00, 0x01, 0x02, 0x03, 0x04])
        self.add_local_name('TestAdvertisement')
        self.include_tx_power = True
        self.add_data(0x26, [0x01, 0x01, 0x00])


def register_ad_cb():
    print( 'Advertisement registered')


def register_ad_error_cb(error):
    print( 'Failed to register advertisement: ' + str(error))
    mainloop.quit()





class InvalidArgsException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.freedesktop.DBus.Error.InvalidArgs'

class NotSupportedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.NotSupported'

class NotPermittedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.NotPermitted'

class InvalidValueLengthException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.InvalidValueLength'

class FailedException(dbus.exceptions.DBusException):
    _dbus_error_name = 'org.bluez.Error.Failed'


class Application(dbus.service.Object):
    """
    org.bluez.GattApplication1 interface implementation
    """
    def __init__(self, bus):
        self.path = '/'
        self.services = []
        dbus.service.Object.__init__(self, bus, self.path)
        self.add_service(HeartRateService(bus, 0))
        self.add_service(BatteryService(bus, 1))
        self.add_service(TestService(bus, 2))

    def get_path(self):
        return dbus.ObjectPath(self.path)

    def add_service(self, service):
        self.services.append(service)

    @dbus.service.method(DBUS_OM_IFACE, out_signature='a{oa{sa{sv}}}')
    def GetManagedObjects(self):
        response = {}
        print('GetManagedObjects')

        for service in self.services:
            response[service.get_path()] = service.get_properties()
            chrcs = service.get_characteristics()
            for chrc in chrcs:
                response[chrc.get_path()] = chrc.get_properties()
                descs = chrc.get_descriptors()
                for desc in descs:
                    response[desc.get_path()] = desc.get_properties()

        return response


class Service(dbus.service.Object):
    """
    org.bluez.GattService1 interface implementation
    """
    PATH_BASE = '/org/bluez/example/service'

    def __init__(self, bus, index, uuid, primary):
        self.path = self.PATH_BASE + str(index)
        self.bus = bus
        self.uuid = uuid
        self.primary = primary
        self.characteristics = []
        dbus.service.Object.__init__(self, bus, self.path)

    def get_properties(self):
        return {
                GATT_SERVICE_IFACE: {
                        'UUID': self.uuid,
                        'Primary': self.primary,
                        'Characteristics': dbus.Array(
                                self.get_characteristic_paths(),
                                signature='o')
                }
        }

    def get_path(self):
        return dbus.ObjectPath(self.path)

    def add_characteristic(self, characteristic):
        self.characteristics.append(characteristic)

    def get_characteristic_paths(self):
        result = []
        for chrc in self.characteristics:
            result.append(chrc.get_path())
        return result

    def get_characteristics(self):
        return self.characteristics

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        if interface != GATT_SERVICE_IFACE:
            raise InvalidArgsException()

        return self.get_properties()[GATT_SERVICE_IFACE]


class Characteristic(dbus.service.Object):
    """
    org.bluez.GattCharacteristic1 interface implementation
    """
    def __init__(self, bus, index, uuid, flags, service):
        self.path = service.path + '/char' + str(index)
        self.bus = bus
        self.uuid = uuid
        self.service = service
        self.flags = flags
        self.descriptors = []
        dbus.service.Object.__init__(self, bus, self.path)

    def get_properties(self):
        return {
                GATT_CHRC_IFACE: {
                        'Service': self.service.get_path(),
                        'UUID': self.uuid,
                        'Flags': self.flags,
                        'Descriptors': dbus.Array(
                                self.get_descriptor_paths(),
                                signature='o')
                }
        }

    def get_path(self):
        return dbus.ObjectPath(self.path)

    def add_descriptor(self, descriptor):
        self.descriptors.append(descriptor)

    def get_descriptor_paths(self):
        result = []
        for desc in self.descriptors:
            result.append(desc.get_path())
        return result

    def get_descriptors(self):
        return self.descriptors

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        if interface != GATT_CHRC_IFACE:
            raise InvalidArgsException()

        return self.get_properties()[GATT_CHRC_IFACE]

    @dbus.service.method(GATT_CHRC_IFACE,
                        in_signature='a{sv}',
                        out_signature='ay')
    def ReadValue(self, options):
        print('Default ReadValue called, returning error')
        raise NotSupportedException()

    @dbus.service.method(GATT_CHRC_IFACE, in_signature='aya{sv}')
    def WriteValue(self, value, options):
        print('Default WriteValue called, returning error')
        raise NotSupportedException()

    @dbus.service.method(GATT_CHRC_IFACE)
    def StartNotify(self):
        print('Default StartNotify called, returning error')
        raise NotSupportedException()

    @dbus.service.method(GATT_CHRC_IFACE)
    def StopNotify(self):
        print('Default StopNotify called, returning error')
        raise NotSupportedException()

    @dbus.service.signal(DBUS_PROP_IFACE,
                         signature='sa{sv}as')
    def PropertiesChanged(self, interface, changed, invalidated):
        pass


class Descriptor(dbus.service.Object):
    """
    org.bluez.GattDescriptor1 interface implementation
    """
    def __init__(self, bus, index, uuid, flags, characteristic):
        self.path = characteristic.path + '/desc' + str(index)
        self.bus = bus
        self.uuid = uuid
        self.flags = flags
        self.chrc = characteristic
        dbus.service.Object.__init__(self, bus, self.path)

    def get_properties(self):
        return {
                GATT_DESC_IFACE: {
                        'Characteristic': self.chrc.get_path(),
                        'UUID': self.uuid,
                        'Flags': self.flags,
                }
        }

    def get_path(self):
        return dbus.ObjectPath(self.path)

    @dbus.service.method(DBUS_PROP_IFACE,
                         in_signature='s',
                         out_signature='a{sv}')
    def GetAll(self, interface):
        if interface != GATT_DESC_IFACE:
            raise InvalidArgsException()

        return self.get_properties()[GATT_DESC_IFACE]

    @dbus.service.method(GATT_DESC_IFACE,
                        in_signature='a{sv}',
                        out_signature='ay')
    def ReadValue(self, options):
        print ('Default ReadValue called, returning error')
        raise NotSupportedException()

    @dbus.service.method(GATT_DESC_IFACE, in_signature='aya{sv}')
    def WriteValue(self, value, options):
        print('Default WriteValue called, returning error')
        raise NotSupportedException()


class HeartRateService(Service):
    """
    Fake Heart Rate Service that simulates a fake heart beat and control point
    behavior.

    """
    HR_UUID = '0000180d-0000-1000-8000-00805f9b34fb'

    def __init__(self, bus, index):
        Service.__init__(self, bus, index, self.HR_UUID, True)
        self.add_characteristic(HeartRateMeasurementChrc(bus, 0, self))
        self.add_characteristic(BodySensorLocationChrc(bus, 1, self))
        self.add_characteristic(HeartRateControlPointChrc(bus, 2, self))
        self.energy_expended = 0


class HeartRateMeasurementChrc(Characteristic):
    HR_MSRMT_UUID = '00002a37-0000-1000-8000-00805f9b34fb'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.HR_MSRMT_UUID,
                ['read', 'notify'],
                service)
        self.notifying = False
        self.hr_ee_count = 0
        

    def ReadValue(self, options):
        print('HeartRateMeasurementChrc Read')
        return [dbus.Byte(6), dbus.Byte(99)]


    def hr_msrmt_cb(self):
        value = []
        value.append(dbus.Byte(0x06))

        value.append(dbus.Byte(randint(90, 130)))

        if self.hr_ee_count % 10 == 0:
            value[0] = dbus.Byte(value[0] | 0x08)
            value.append(dbus.Byte(self.service.energy_expended & 0xff))
            value.append(dbus.Byte((self.service.energy_expended >> 8) & 0xff))

        self.service.energy_expended = \
                min(0xffff, self.service.energy_expended + 1)
        self.hr_ee_count += 1

        print('Updating value: ' + repr(value))

        self.PropertiesChanged(GATT_CHRC_IFACE, { 'Value': value }, [])

        return self.notifying

    def _update_hr_msrmt_simulation(self):
        print('Update HR Measurement Simulation')

        if not self.notifying:
            return

        GObject.timeout_add(1000, self.hr_msrmt_cb)

    def StartNotify(self):
        if self.notifying:
            print('Already notifying, nothing to do')
            return

        self.notifying = True
        self._update_hr_msrmt_simulation()

    def StopNotify(self):
        if not self.notifying:
            print('Not notifying, nothing to do')
            return

        self.notifying = False
        self._update_hr_msrmt_simulation()


class BodySensorLocationChrc(Characteristic):
    BODY_SNSR_LOC_UUID = '00002a38-0000-1000-8000-00805f9b34fb'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.BODY_SNSR_LOC_UUID,
                ['read', 'notify'],
                service)
        self.notifying = False
        self.value = [0x01]

    def ReadValue(self, options):
        # Return 'Chest' as the sensor location.
        return [ 0x02 ]


    def _cb(self):
        value = []

        value.append(dbus.Byte(randint(1, 3)))

        print('Updating value: ' + repr(value))

        self.PropertiesChanged(GATT_CHRC_IFACE, { 'Value': value }, [])

        return self.notifying

    def _update_simulation(self):
        print('Update Simulation')

        if not self.notifying:
            return

        GObject.timeout_add(1000, self._cb)

    def StartNotify(self):
        if self.notifying:
            print('Already notifying, nothing to do')
            return

        self.notifying = True
        self._update_simulation()

    def StopNotify(self):
        if not self.notifying:
            print('Not notifying, nothing to do')
            return

        self.notifying = False
        self._update_simulation()


class HeartRateControlPointChrc(Characteristic):
    HR_CTRL_PT_UUID = '00002a39-0000-1000-8000-00805f9b34fb'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.HR_CTRL_PT_UUID,
                ['write'],
                service)

    def WriteValue(self, value, options):
        print('Heart Rate Control Point WriteValue called')

        if len(value) != 1:
            raise InvalidValueLengthException()

        byte = value[0]
        print('Control Point value: ' + repr(byte))

        if byte != 1:
            raise FailedException("0x80")

        print('Energy Expended field reset!')
        self.service.energy_expended = 0


class BatteryService(Service):
    """
    Fake Battery service that emulates a draining battery.

    """
    BATTERY_UUID = '180f'

    def __init__(self, bus, index):
        Service.__init__(self, bus, index, self.BATTERY_UUID, True)
        self.add_characteristic(BatteryLevelCharacteristic(bus, 0, self))


class BatteryLevelCharacteristic(Characteristic):
    """
    Fake Battery Level characteristic. The battery level is drained by 2 points
    every 5 seconds.

    """
    BATTERY_LVL_UUID = '2a19'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.BATTERY_LVL_UUID,
                ['read', 'notify'],
                service)
        self.notifying = False
        self.battery_lvl = 100
        GObject.timeout_add(5000, self.drain_battery)

    def notify_battery_level(self):
        if not self.notifying:
            return
        self.PropertiesChanged(
                GATT_CHRC_IFACE,
                { 'Value': [dbus.Byte(self.battery_lvl)] }, [])

    def drain_battery(self):
        if not self.notifying:
            return True
        if self.battery_lvl > 0:
            self.battery_lvl -= 2
            if self.battery_lvl < 0:
                self.battery_lvl = 0
        print('Battery Level drained: ' + repr(self.battery_lvl))
        self.notify_battery_level()
        return True

    def ReadValue(self, options):
        print('Battery Level read: ' + repr(self.battery_lvl))
        return [dbus.Byte(self.battery_lvl)]

    def StartNotify(self):
        if self.notifying:
            print('Already notifying, nothing to do')
            return

        self.notifying = True
        self.notify_battery_level()

    def StopNotify(self):
        if not self.notifying:
            print('Not notifying, nothing to do')
            return

        self.notifying = False


class TestService(Service):
    """
    Dummy test service that provides characteristics and descriptors that
    exercise various API functionality.

    """
    TEST_SVC_UUID = '12345678-1234-5678-1234-56789abcdef0'

    def __init__(self, bus, index):
        Service.__init__(self, bus, index, self.TEST_SVC_UUID, True)
        self.add_characteristic(TestCharacteristic(bus, 0, self))
        self.add_characteristic(TestEncryptCharacteristic(bus, 1, self))
        self.add_characteristic(TestSecureCharacteristic(bus, 2, self))

class TestCharacteristic(Characteristic):
    """
    Dummy test characteristic. Allows writing arbitrary bytes to its value, and
    contains "extended properties", as well as a test descriptor.

    """
    TEST_CHRC_UUID = '12345678-1234-5678-1234-56789abcdef1'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.TEST_CHRC_UUID,
                ['read', 'write', 'writable-auxiliaries'],
                service)
        self.value = []
        self.add_descriptor(TestDescriptor(bus, 0, self))
        self.add_descriptor(
                CharacteristicUserDescriptionDescriptor(bus, 1, self))

    def ReadValue(self, options):
        print('TestCharacteristic Read: ' + repr(self.value))
        return self.value

    def WriteValue(self, value, options):
        print('TestCharacteristic Write: ' + repr(value))
        self.value = value


class TestDescriptor(Descriptor):
    """
    Dummy test descriptor. Returns a static value.

    """
    TEST_DESC_UUID = '12345678-1234-5678-1234-56789abcdef2'

    def __init__(self, bus, index, characteristic):
        Descriptor.__init__(
                self, bus, index,
                self.TEST_DESC_UUID,
                ['read', 'write'],
                characteristic)

    def ReadValue(self, options):
        return [
                dbus.Byte('T'), dbus.Byte('e'), dbus.Byte('s'), dbus.Byte('t')
        ]


class CharacteristicUserDescriptionDescriptor(Descriptor):
    """
    Writable CUD descriptor.

    """
    CUD_UUID = '2901'

    def __init__(self, bus, index, characteristic):
        self.writable = 'writable-auxiliaries' in characteristic.flags
        self.value = array.array('B', b'This is a characteristic for testing')
        self.value = self.value.tolist()
        Descriptor.__init__(
                self, bus, index,
                self.CUD_UUID,
                ['read', 'write'],
                characteristic)

    def ReadValue(self, options):
        return self.value

    def WriteValue(self, value, options):
        if not self.writable:
            raise NotPermittedException()
        self.value = value

class TestEncryptCharacteristic(Characteristic):
    """
    Dummy test characteristic requiring encryption.

    """
    TEST_CHRC_UUID = '12345678-1234-5678-1234-56789abcdef3'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.TEST_CHRC_UUID,
                ['encrypt-read', 'encrypt-write'],
                service)
        self.value = []
        self.add_descriptor(TestEncryptDescriptor(bus, 2, self))
        self.add_descriptor(
                CharacteristicUserDescriptionDescriptor(bus, 3, self))

    def ReadValue(self, options):
        print('TestEncryptCharacteristic Read: ' + repr(self.value))
        return self.value

    def WriteValue(self, value, options):
        print('TestEncryptCharacteristic Write: ' + repr(value))
        self.value = value

class TestEncryptDescriptor(Descriptor):
    """
    Dummy test descriptor requiring encryption. Returns a static value.

    """
    TEST_DESC_UUID = '12345678-1234-5678-1234-56789abcdef4'

    def __init__(self, bus, index, characteristic):
        Descriptor.__init__(
                self, bus, index,
                self.TEST_DESC_UUID,
                ['encrypt-read', 'encrypt-write'],
                characteristic)

    def ReadValue(self, options):
        return [
                dbus.Byte('T'), dbus.Byte('e'), dbus.Byte('s'), dbus.Byte('t')
        ]


class TestSecureCharacteristic(Characteristic):
    """
    Dummy test characteristic requiring secure connection.

    """
    TEST_CHRC_UUID = '12345678-1234-5678-1234-56789abcdef5'

    def __init__(self, bus, index, service):
        Characteristic.__init__(
                self, bus, index,
                self.TEST_CHRC_UUID,
                ['secure-read', 'secure-write'],
                service)
        self.value = []
        self.add_descriptor(TestSecureDescriptor(bus, 2, self))
        self.add_descriptor(
                CharacteristicUserDescriptionDescriptor(bus, 3, self))

    def ReadValue(self, options):
        print('TestSecureCharacteristic Read: ' + repr(self.value))
        return self.value

    def WriteValue(self, value, options):
        print('TestSecureCharacteristic Write: ' + repr(value))
        self.value = value


class TestSecureDescriptor(Descriptor):
    """
    Dummy test descriptor requiring secure connection. Returns a static value.

    """
    TEST_DESC_UUID = '12345678-1234-5678-1234-56789abcdef6'

    def __init__(self, bus, index, characteristic):
        Descriptor.__init__(
                self, bus, index,
                self.TEST_DESC_UUID,
                ['secure-read', 'secure-write'],
                characteristic)

    def ReadValue(self, options):
        return [
                dbus.Byte('T'), dbus.Byte('e'), dbus.Byte('s'), dbus.Byte('t')
        ]

def register_app_cb():
    print('GATT application registered')


def register_app_error_cb(error):
    print('Failed to register application: ' + str(error))
    mainloop.quit()


def find_adapter(bus):
    remote_om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'),
                               DBUS_OM_IFACE)
    objects = remote_om.GetManagedObjects()

    for o, props in objects.items():
        if GATT_MANAGER_IFACE in props.keys():
            return o

    return None

def main():
    global mainloop

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()

    adapter = find_adapter(bus)
    if not adapter:
        print('GattManager1 interface not found')
        return

    service_manager = dbus.Interface(
            bus.get_object(BLUEZ_SERVICE_NAME, adapter),
            GATT_MANAGER_IFACE)

    app = Application(bus)

    mainloop = GObject.MainLoop()

    print('Registering GATT application...')

    service_manager.RegisterApplication(app.get_path(), {},
                                    reply_handler=register_app_cb,
                                    error_handler=register_app_error_cb)


    # Advert
    if not adapter:
        print( 'LEAdvertisingManager1 interface not found')
        return

    adapter_props = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter),
                                   "org.freedesktop.DBus.Properties");

    adapter_props.Set("org.bluez.Adapter1", "Powered", dbus.Boolean(1))

    ad_manager = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, adapter),
                                LE_ADVERTISING_MANAGER_IFACE)

    test_advertisement = TestAdvertisement(bus, 0)

    ad_manager.RegisterAdvertisement(test_advertisement.get_path(), {},
                                     reply_handler=register_ad_cb,
                                     error_handler=register_ad_error_cb)

    mainloop.run()

if __name__ == '__main__':
    main()


[-- Attachment #4: btmon_notify.log --]
[-- Type: application/octet-stream, Size: 12288 bytes --]

Bluetooth monitor ver 5.48
= Note: Linux version 4.19.35-g92e18fefc77 (armv7l)                    0.809169
= Note: Bluetooth subsystem version 2.22                               0.809182
= New Index: 00:16:A4:4A:2D:27 (Primary,UART,hci0)              [hci0] 0.809187
= Open Index: 00:16:A4:4A:2D:27                                 [hci0] 0.809190
= Index Info: 00:16:A4:4.. (Cypress Semiconductor Corporation)  [hci0] 0.809194
@ MGMT Open: bluetoothd (privileged) version 1.14             {0x0002} 0.809200
@ MGMT Open: bluetoothd (privileged) version 1.14             {0x0001} 0.809203
@ MGMT Open: btmon (privileged) version 1.14                  {0x0003} 0.809276
> ACL Data RX: Handle 65 flags 0x02 dlen 8                   #1 [hci0] 4.543721
      ATT: Handle Value Notification (0x1b) len 3
        Handle: 0x0016
          Data: 64
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #2 [hci0] 6.883753
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0001-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 30                  #3 [hci0] 6.884412
      ATT: Read By Group Type Response (0x11) len 25
        Attribute data length: 6
        Attribute group list: 4 entries
        Handle range: 0x0001-0x0005
        UUID: Generic Access Profile (0x1800)
        Handle range: 0x0006-0x0009
        UUID: Generic Attribute Profile (0x1801)
        Handle range: 0x0234-0x023c
        UUID: Heart Rate (0x180d)
        Handle range: 0x023d-0x0240
        UUID: Battery Service (0x180f)
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #4 [hci0] 6.944638
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0241-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 26                  #5 [hci0] 6.945293
      ATT: Read By Group Type Response (0x11) len 21
        Attribute data length: 20
        Attribute group list: 1 entry
        Handle range: 0x0241-0x0250
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef0)
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #6 [hci0] 7.004723
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0251-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 9                   #7 [hci0] 7.005369
      ATT: Error Response (0x01) len 4
        Read By Group Type Request (0x10)
        Handle: 0x0251
        Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5       #8 [hci0] 7.005549
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #9 [hci0] 7.064450
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0234-0x023c
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 27                 #10 [hci0] 7.065112
      ATT: Read By Type Response (0x09) len 22
        Attribute data length: 7
        Attribute data list: 3 entries
        Handle: 0x0235
        Value: 123602372a
        Handle: 0x0238
        Value: 123902382a
        Handle: 0x023b
        Value: 083c02392a
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #11 [hci0] 7.124428
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x023d-0x0240
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 13                 #12 [hci0] 7.125226
      ATT: Read By Type Response (0x09) len 8
        Attribute data length: 7
        Attribute data list: 1 entry
        Handle: 0x023e
        Value: 123f02192a
> HCI Event: Number of Completed Packets (0x13) plen 5      #13 [hci0] 7.125376
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #14 [hci0] 7.184416
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0241-0x0250
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 69                 #15 [hci0] 7.185101
      ATT: Read By Type Response (0x09) len 64
        Attribute data length: 21
        Attribute data list: 3 entries
        Handle: 0x0242
        Value: 8a4302f1debc9a785634127856341278563412
        Handle: 0x0247
        Value: 8a4802f3debc9a785634127856341278563412
        Handle: 0x024c
        Value: 8a4d02f5debc9a785634127856341278563412
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #16 [hci0] 7.244526
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x024e-0x0250
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 9                  #17 [hci0] 7.246144
      ATT: Error Response (0x01) len 4
        Read By Type Request (0x08)
        Handle: 0x024e
        Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5      #18 [hci0] 7.246564
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #19 [hci0] 7.304500
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0237-0x0237
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #20 [hci0] 7.305951
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0237
        UUID: Client Characteristic Configuration (0x2902)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #21 [hci0] 7.364540
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x023a-0x023a
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #22 [hci0] 7.366242
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x023a
        UUID: Client Characteristic Configuration (0x2902)
> HCI Event: Number of Completed Packets (0x13) plen 5      #23 [hci0] 7.366660
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #24 [hci0] 7.424617
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0240-0x0240
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #25 [hci0] 7.426085
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0240
        UUID: Client Characteristic Configuration (0x2902)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #26 [hci0] 7.484523
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0244-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #27 [hci0] 7.486104
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0244
        UUID: Characteristic Extended Properties (0x2900)
> HCI Event: Number of Completed Packets (0x13) plen 5      #28 [hci0] 7.486520
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #29 [hci0] 7.544546
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0245-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #30 [hci0] 7.546011
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x0245
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef2)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #31 [hci0] 7.604713
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0246-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #32 [hci0] 7.606323
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0246
        UUID: Characteristic User Description (0x2901)
> HCI Event: Number of Completed Packets (0x13) plen 5      #33 [hci0] 7.606747
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #34 [hci0] 7.664243
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0249-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #35 [hci0] 7.665862
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0249
        UUID: Characteristic Extended Properties (0x2900)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #36 [hci0] 7.724603
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024a-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #37 [hci0] 7.726315
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x024a
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef4)
> HCI Event: Number of Completed Packets (0x13) plen 5      #38 [hci0] 7.726625
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #39 [hci0] 7.784545
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024b-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #40 [hci0] 7.785996
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x024b
        UUID: Characteristic User Description (0x2901)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #41 [hci0] 7.844187
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024e-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #42 [hci0] 7.845777
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x024e
        UUID: Characteristic Extended Properties (0x2900)
> HCI Event: Number of Completed Packets (0x13) plen 5      #43 [hci0] 7.846215
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #44 [hci0] 7.904466
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024f-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #45 [hci0] 7.906160
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x024f
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef6)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #46 [hci0] 7.964493
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0250-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #47 [hci0] 7.966067
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0250
        UUID: Characteristic User Description (0x2901)
> HCI Event: Number of Completed Packets (0x13) plen 5      #48 [hci0] 7.966489
        Num handles: 1
        Handle: 65
        Count: 2
> HCI Event: Number of Completed Packets (0x13) plen 5      #49 [hci0] 8.203559
        Num handles: 1
        Handle: 65
        Count: 1
> ACL Data RX: Handle 65 flags 0x02 dlen 7                 #50 [hci0] 11.833674
      ATT: Read Request (0x0a) len 2
        Handle: 0x0236
< ACL Data TX: Handle 65 flags 0x00 dlen 7                 #51 [hci0] 11.840770
      ATT: Read Response (0x0b) len 2
        Value: 0663
> HCI Event: Number of Completed Packets (0x13) plen 5     #52 [hci0] 12.078687
        Num handles: 1
        Handle: 65
        Count: 1
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #53 [hci0] 14.055212
      ATT: Write Request (0x12) len 4
        Handle: 0x0237
          Data: 0100
< ACL Data TX: Handle 65 flags 0x00 dlen 5                 #54 [hci0] 14.056230
      ATT: Write Response (0x13) len 0
> HCI Event: Number of Completed Packets (0x13) plen 5     #55 [hci0] 14.329045
        Num handles: 1
        Handle: 65
        Count: 1
< ACL Data TX: Handle 65 flags 0x00 dlen 11                #56 [hci0] 15.078671
      ATT: Handle Value Notification (0x1b) len 6
        Handle: 0x0236
          Data: 0e750000
> HCI Event: Number of Completed Packets (0x13) plen 5     #57 [hci0] 15.330353
        Num handles: 1
        Handle: 65
        Count: 1
< ACL Data TX: Handle 65 flags 0x00 dlen 9                 #58 [hci0] 16.071839
      ATT: Handle Value Notification (0x1b) len 4
        Handle: 0x0236
          Data: 066e
> ACL Data RX: H

[-- Attachment #5: btmon_read.log --]
[-- Type: application/octet-stream, Size: 8192 bytes --]

Bluetooth monitor ver 5.48
= Note: Linux version 4.19.35-g92e18fefc77 (armv7l)                    0.120439
= Note: Bluetooth subsystem version 2.22                               0.120453
= New Index: 00:16:A4:4A:2D:27 (Primary,UART,hci0)              [hci0] 0.120458
= Open Index: 00:16:A4:4A:2D:27                                 [hci0] 0.120461
= Index Info: 00:16:A4:4.. (Cypress Semiconductor Corporation)  [hci0] 0.120464
@ MGMT Open: bluetoothd (privileged) version 1.14             {0x0002} 0.120470
@ MGMT Open: bluetoothd (privileged) version 1.14             {0x0001} 0.120473
@ MGMT Open: btmon (privileged) version 1.14                  {0x0003} 0.120600
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #1 [hci0] 18.221960
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0001-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 30                 #2 [hci0] 18.223778
      ATT: Read By Group Type Response (0x11) len 25
        Attribute data length: 6
        Attribute group list: 4 entries
        Handle range: 0x0001-0x0005
        UUID: Generic Access Profile (0x1800)
        Handle range: 0x0006-0x0009
        UUID: Generic Attribute Profile (0x1801)
        Handle range: 0x0219-0x021f
        UUID: Heart Rate (0x180d)
        Handle range: 0x0220-0x0223
        UUID: Battery Service (0x180f)
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #3 [hci0] 18.282653
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0224-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 26                 #4 [hci0] 18.284160
      ATT: Read By Group Type Response (0x11) len 21
        Attribute data length: 20
        Attribute group list: 1 entry
        Handle range: 0x0224-0x0233
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef0)
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #5 [hci0] 18.342738
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0234-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 9                  #6 [hci0] 18.344380
      ATT: Error Response (0x01) len 4
        Read By Group Type Request (0x10)
        Handle: 0x0234
        Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5      #7 [hci0] 18.344800
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #8 [hci0] 18.402726
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0219-0x021f
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 27                 #9 [hci0] 18.404252
      ATT: Read By Type Response (0x09) len 22
        Attribute data length: 7
        Attribute data list: 3 entries
        Handle: 0x021a
        Value: 021b02372a
        Handle: 0x021c
        Value: 021d02382a
        Handle: 0x021e
        Value: 081f02392a
> ACL Data RX: Handle 65 flags 0x02 dlen 11                #10 [hci0] 18.462933
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0220-0x0223
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 13                #11 [hci0] 18.464430
      ATT: Read By Type Response (0x09) len 8
        Attribute data length: 7
        Attribute data list: 1 entry
        Handle: 0x0221
        Value: 122202192a
> HCI Event: Number of Completed Packets (0x13) plen 5     #12 [hci0] 18.464727
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 11                #13 [hci0] 18.522662
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0224-0x0233
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 69                #14 [hci0] 18.524197
      ATT: Read By Type Response (0x09) len 64
        Attribute data length: 21
        Attribute data list: 3 entries
        Handle: 0x0225
        Value: 8a2602f1debc9a785634127856341278563412
        Handle: 0x022a
        Value: 8a2b02f3debc9a785634127856341278563412
        Handle: 0x022f
        Value: 8a3002f5debc9a785634127856341278563412
> ACL Data RX: Handle 65 flags 0x02 dlen 11                #15 [hci0] 18.582710
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0231-0x0233
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 9                 #16 [hci0] 18.584481
      ATT: Error Response (0x01) len 4
        Read By Type Request (0x08)
        Handle: 0x0231
        Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5     #17 [hci0] 18.584906
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #18 [hci0] 18.642163
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0223-0x0223
< ACL Data TX: Handle 65 flags 0x00 dlen 10                #19 [hci0] 18.643653
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0223
        UUID: Client Characteristic Configuration (0x2902)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #20 [hci0] 18.702679
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0227-0x0229
< ACL Data TX: Handle 65 flags 0x00 dlen 10                #21 [hci0] 18.704247
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0227
        UUID: Characteristic Extended Properties (0x2900)
> HCI Event: Number of Completed Packets (0x13) plen 5     #22 [hci0] 18.704664
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #23 [hci0] 18.762536
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0228-0x0229
< ACL Data TX: Handle 65 flags 0x00 dlen 24                #24 [hci0] 18.763395
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x0228
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef2)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #25 [hci0] 18.822612
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0229-0x0229
< ACL Data TX: Handle 65 flags 0x00 dlen 10                #26 [hci0] 18.823295
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0229
        UUID: Characteristic User Description (0x2901)
> HCI Event: Number of Completed Packets (0x13) plen 5     #27 [hci0] 18.823497
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #28 [hci0] 18.882546
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x022c-0x022e
< ACL Data TX: Handle 65 flags 0x00 dlen 10                #29 [hci0] 18.883175
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x022c
        UUID: Characteristic Extended Properties (0x2900)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #30 [hci0] 18.942642
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x022d-0x022e
< ACL Data TX: Handle 65 flags 0x00 dlen 24                #31 [hci0] 18.943322
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x022d
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef4)
> HCI Event: Number of Completed Packets (0x13) plen 5     #32 [hci0] 18.943467
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #33 [hci0] 19.002738
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x022e-0x022e
< ACL Data TX: Handle 65 flags 0x00 dlen 10                #34 [hci0] 19.003768
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x022e
        UUID: Characteristic User Description (0x2901)
> ACL Data RX: Handle 6

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

* Re: How to add "Service Changed Indication"
  2021-01-27  8:50           ` Kenny Bian
@ 2021-01-28 19:48             ` Kenny Bian
  0 siblings, 0 replies; 8+ messages in thread
From: Kenny Bian @ 2021-01-28 19:48 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

[-- Attachment #1: Type: text/plain, Size: 19916 bytes --]

Hi Luiz,

I read the btmon log after changing some services. But I don't see
there is any info about "Service Changed Indication". I attach this
log to this email. Could you please take a look at the log?

Some questions I have are:
1. To enable the "Service Changed Indication", do I need to change the
configuration of the bluetooth GATT server?
2. To enable the "Service Changed Indication", do I need to write some
code in Python to have it?
3. If I just need to call RegisterApplication() to register the
service and "Service Changed Indication" is supposed to be enabled,
then we should be fine on the GATT server side, correct? Then it'll be
up to the app developer to check on the mobile side. Do you know what
the app developer should check on their side?
4. I ran "bluetoothctl" and found these info:
[NEW] Characteristic
        /org/bluez/hci0/dev_6C_96_CF_98_99_12/service0006/char0007
        00002a05-0000-1000-8000-00805f9b34fb
        Service Changed
What is the meaning of this info? Can we tell from this info that
"Service Changed Indication" is working?

Thanks in advance!

On Wed, Jan 27, 2021 at 12:50 AM Kenny Bian <kennybian@gmail.com> wrote:
>
> Hi Luiz,
>
> I'm not sure if I can attach files to this forum. I just try to attach
> the files about the "Service Changed Indication" issue.
>
> Here is the list of files:
> bt_read.py - the script that the "Heart Rate Measurement" and "Body
> Sensor Location" characteristics only have the Read attribute
> bt_notify.py - the script that the "Heart Rate Measurement" and "Body
> Sensor Location" characteristics only have both the Read and Notify
> attributes
> btmon_read.log - the btmon log when running bt_read.py
> btmon_notify.log - the btmon log when running bt_notify.py
>
> Thank you very much!
>
> On Wed, Jan 27, 2021 at 12:46 AM Kenny Bian <kennybian@gmail.com> wrote:
> >
> > Hi Luiz,
> >
> > On Wed, Jan 27, 2021 at 12:42 AM Kenny Bian <kennybian@gmail.com> wrote:
> > >
> > > Hi Luiz,
> > >
> > > Thank you so much for your information.
> > >
> > > I created a test GATT server from the sample
> > > code(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> > > I have 2 python scripts. In the "bt_read.py" I created, the Heart Rate
> > > Measurement(2A37) and Body Sensor Location(2A38) only have Read
> > > attribute. In the "bt_notify.py" I created, the Heart Rate
> > > Measurement(2A37) and Body Sensor Location(2A38) only have both the
> > > Read and Notify attribute.
> > >
> > > Here is what I did:
> > > I ran the "bt_read.py" and captured the btmon log. Then I ran
> > > "bt_notify.py" and captured the btmon log. I read both logs. But I
> > > don't see there is any info regarding the "Service Changed
> > > Indication".
> > >
> > > Here is the btmon log with both the Read and Notify attributes below.
> > > Thanks again for your help!
> > > =========================================================================
> > > Bluetooth monitor ver 5.48
> > > = Note: Linux version 4.19.35-g92e18fefc77 (armv7l)                    0.809169
> > > = Note: Bluetooth subsystem version 2.22                               0.809182
> > > = New Index: 00:16:A4:4A:2D:27 (Primary,UART,hci0)              [hci0] 0.809187
> > > = Open Index: 00:16:A4:4A:2D:27                                 [hci0] 0.809190
> > > = Index Info: 00:16:A4:4.. (Cypress Semiconductor Corporation)  [hci0] 0.809194
> > > @ MGMT Open: bluetoothd (privileged) version 1.14             {0x0002} 0.809200
> > > @ MGMT Open: bluetoothd (privileged) version 1.14             {0x0001} 0.809203
> > > @ MGMT Open: btmon (privileged) version 1.14                  {0x0003} 0.809276
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 8                   #1 [hci0] 4.543721
> > >       ATT: Handle Value Notification (0x1b) len 3
> > >         Handle: 0x0016
> > >           Data: 64
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #2 [hci0] 6.883753
> > >       ATT: Read By Group Type Request (0x10) len 6
> > >         Handle range: 0x0001-0xffff
> > >         Attribute group type: Primary Service (0x2800)
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 30                  #3 [hci0] 6.884412
> > >       ATT: Read By Group Type Response (0x11) len 25
> > >         Attribute data length: 6
> > >         Attribute group list: 4 entries
> > >         Handle range: 0x0001-0x0005
> > >         UUID: Generic Access Profile (0x1800)
> > >         Handle range: 0x0006-0x0009
> > >         UUID: Generic Attribute Profile (0x1801)
> > >         Handle range: 0x0234-0x023c
> > >         UUID: Heart Rate (0x180d)
> > >         Handle range: 0x023d-0x0240
> > >         UUID: Battery Service (0x180f)
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #4 [hci0] 6.944638
> > >       ATT: Read By Group Type Request (0x10) len 6
> > >         Handle range: 0x0241-0xffff
> > >         Attribute group type: Primary Service (0x2800)
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 26                  #5 [hci0] 6.945293
> > >       ATT: Read By Group Type Response (0x11) len 21
> > >         Attribute data length: 20
> > >         Attribute group list: 1 entry
> > >         Handle range: 0x0241-0x0250
> > >         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef0)
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #6 [hci0] 7.004723
> > >       ATT: Read By Group Type Request (0x10) len 6
> > >         Handle range: 0x0251-0xffff
> > >         Attribute group type: Primary Service (0x2800)
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 9                   #7 [hci0] 7.005369
> > >       ATT: Error Response (0x01) len 4
> > >         Read By Group Type Request (0x10)
> > >         Handle: 0x0251
> > >         Error: Attribute Not Found (0x0a)
> > > > HCI Event: Number of Completed Packets (0x13) plen 5       #8 [hci0] 7.005549
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 11                  #9 [hci0] 7.064450
> > >       ATT: Read By Type Request (0x08) len 6
> > >         Handle range: 0x0234-0x023c
> > >         Attribute type: Characteristic (0x2803)
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 27                 #10 [hci0] 7.065112
> > >       ATT: Read By Type Response (0x09) len 22
> > >         Attribute data length: 7
> > >         Attribute data list: 3 entries
> > >         Handle: 0x0235
> > >         Value: 123602372a
> > >         Handle: 0x0238
> > >         Value: 123902382a
> > >         Handle: 0x023b
> > >         Value: 083c02392a
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #11 [hci0] 7.124428
> > >       ATT: Read By Type Request (0x08) len 6
> > >         Handle range: 0x023d-0x0240
> > >         Attribute type: Characteristic (0x2803)
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 13                 #12 [hci0] 7.125226
> > >       ATT: Read By Type Response (0x09) len 8
> > >         Attribute data length: 7
> > >         Attribute data list: 1 entry
> > >         Handle: 0x023e
> > >         Value: 123f02192a
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #13 [hci0] 7.125376
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #14 [hci0] 7.184416
> > >       ATT: Read By Type Request (0x08) len 6
> > >         Handle range: 0x0241-0x0250
> > >         Attribute type: Characteristic (0x2803)
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 69                 #15 [hci0] 7.185101
> > >       ATT: Read By Type Response (0x09) len 64
> > >         Attribute data length: 21
> > >         Attribute data list: 3 entries
> > >         Handle: 0x0242
> > >         Value: 8a4302f1debc9a785634127856341278563412
> > >         Handle: 0x0247
> > >         Value: 8a4802f3debc9a785634127856341278563412
> > >         Handle: 0x024c
> > >         Value: 8a4d02f5debc9a785634127856341278563412
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 11                 #16 [hci0] 7.244526
> > >       ATT: Read By Type Request (0x08) len 6
> > >         Handle range: 0x024e-0x0250
> > >         Attribute type: Characteristic (0x2803)
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 9                  #17 [hci0] 7.246144
> > >       ATT: Error Response (0x01) len 4
> > >         Read By Type Request (0x08)
> > >         Handle: 0x024e
> > >         Error: Attribute Not Found (0x0a)
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #18 [hci0] 7.246564
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #19 [hci0] 7.304500
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x0237-0x0237
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #20 [hci0] 7.305951
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x0237
> > >         UUID: Client Characteristic Configuration (0x2902)
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #21 [hci0] 7.364540
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x023a-0x023a
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #22 [hci0] 7.366242
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x023a
> > >         UUID: Client Characteristic Configuration (0x2902)
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #23 [hci0] 7.366660
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #24 [hci0] 7.424617
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x0240-0x0240
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #25 [hci0] 7.426085
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x0240
> > >         UUID: Client Characteristic Configuration (0x2902)
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #26 [hci0] 7.484523
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x0244-0x0246
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #27 [hci0] 7.486104
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x0244
> > >         UUID: Characteristic Extended Properties (0x2900)
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #28 [hci0] 7.486520
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #29 [hci0] 7.544546
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x0245-0x0246
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #30 [hci0] 7.546011
> > >       ATT: Find Information Response (0x05) len 19
> > >         Format: UUID-128 (0x02)
> > >         Handle: 0x0245
> > >         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef2)
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #31 [hci0] 7.604713
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x0246-0x0246
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #32 [hci0] 7.606323
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x0246
> > >         UUID: Characteristic User Description (0x2901)
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #33 [hci0] 7.606747
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #34 [hci0] 7.664243
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x0249-0x024b
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #35 [hci0] 7.665862
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x0249
> > >         UUID: Characteristic Extended Properties (0x2900)
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #36 [hci0] 7.724603
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x024a-0x024b
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #37 [hci0] 7.726315
> > >       ATT: Find Information Response (0x05) len 19
> > >         Format: UUID-128 (0x02)
> > >         Handle: 0x024a
> > >         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef4)
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #38 [hci0] 7.726625
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #39 [hci0] 7.784545
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x024b-0x024b
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #40 [hci0] 7.785996
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x024b
> > >         UUID: Characteristic User Description (0x2901)
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #41 [hci0] 7.844187
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x024e-0x0250
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #42 [hci0] 7.845777
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x024e
> > >         UUID: Characteristic Extended Properties (0x2900)
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #43 [hci0] 7.846215
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #44 [hci0] 7.904466
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x024f-0x0250
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 24                 #45 [hci0] 7.906160
> > >       ATT: Find Information Response (0x05) len 19
> > >         Format: UUID-128 (0x02)
> > >         Handle: 0x024f
> > >         UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef6)
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                  #46 [hci0] 7.964493
> > >       ATT: Find Information Request (0x04) len 4
> > >         Handle range: 0x0250-0x0250
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 10                 #47 [hci0] 7.966067
> > >       ATT: Find Information Response (0x05) len 5
> > >         Format: UUID-16 (0x01)
> > >         Handle: 0x0250
> > >         UUID: Characteristic User Description (0x2901)
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #48 [hci0] 7.966489
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 2
> > > > HCI Event: Number of Completed Packets (0x13) plen 5      #49 [hci0] 8.203559
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 1
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 7                 #50 [hci0] 11.833674
> > >       ATT: Read Request (0x0a) len 2
> > >         Handle: 0x0236
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 7                 #51 [hci0] 11.840770
> > >       ATT: Read Response (0x0b) len 2
> > >         Value: 0663
> > > > HCI Event: Number of Completed Packets (0x13) plen 5     #52 [hci0] 12.078687
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 1
> > > > ACL Data RX: Handle 65 flags 0x02 dlen 9                 #53 [hci0] 14.055212
> > >       ATT: Write Request (0x12) len 4
> > >         Handle: 0x0237
> > >           Data: 0100
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 5                 #54 [hci0] 14.056230
> > >       ATT: Write Response (0x13) len 0
> > > > HCI Event: Number of Completed Packets (0x13) plen 5     #55 [hci0] 14.329045
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 1
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 11                #56 [hci0] 15.078671
> > >       ATT: Handle Value Notification (0x1b) len 6
> > >         Handle: 0x0236
> > >           Data: 0e750000
> > > > HCI Event: Number of Completed Packets (0x13) plen 5     #57 [hci0] 15.330353
> > >         Num handles: 1
> > >         Handle: 65
> > >         Count: 1
> > > < ACL Data TX: Handle 65 flags 0x00 dlen 9                 #58 [hci0] 16.071839
> > >       ATT: Handle Value Notification (0x1b) len 4
> > >         Handle: 0x0236
> > >           Data: 066e
> > > > ACL Data RX: H
> > >
> > > On Mon, Jan 25, 2021 at 9:59 AM Luiz Augusto von Dentz
> > > <luiz.dentz@gmail.com> wrote:
> > > >
> > > > Hi Kenny,
> > > >
> > > > On Sun, Jan 24, 2021 at 10:42 PM Kenny Bian <kennybian@gmail.com> wrote:
> > > > >
> > > > > Hi Luiz,
> > > > >
> > > > > Thank you so much for your reply. I appreciate it.
> > > > >
> > > > > By "registering the services", do you mean "RegisterApplication()" in
> > > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server#n656?
> > > > > If that is the case, I believe I already registered the services.
> > > > > I checked the files in /var/lib/bluetooth. According to
> > > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/settings-storage.txt#n321,
> > > > > there should be a "[ServiceChanged]" section in the "info" file. But I
> > > > > don't see it in the "info" file. Is there a way to tell the "Service
> > > > > Changed Indication" is actually working?
> > > > > Let's suppose the "Service Changed Indication" is already enabled, is
> > > > > there a way for the mobile app to check on their side to tell which
> > > > > service(s) got changed?
> > > >
> > > > HCI traces (btmon) should be able to tell you if it has been
> > > > subscribed or not, if there is an Indication in it it probably means
> > > > the remote has subscribed.
> > > >
> > > > > Thanks again for your help.
> > > > >
> > > > > On Sun, Jan 24, 2021 at 7:35 PM Luiz Augusto von Dentz
> > > > > <luiz.dentz@gmail.com> wrote:
> > > > > >
> > > > > > Hi Kenny,
> > > > > >
> > > > > > On Sun, Jan 24, 2021 at 12:45 AM Kenny Bian <kennybian@gmail.com> wrote:
> > > > > > >
> > > > > > > Hello,
> > > > > > >
> > > > > > > We implemented a GATT server on Linux in Python. The code is based on
> > > > > > > the code sample(https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-gatt-server).
> > > > > > > The BlueZ version is 5.48. But we found a problem. The cached data in
> > > > > > > /var/lib/bluetooth caused the mobile app to crash if some
> > > > > > > characteristics are changed. After some research, we found "Under BLE
> > > > > > > standard 'Generic Attribute'(0x1801), there is a Characteristic
> > > > > > > 'Service Changed' (0x2A05) with 'indicate' property", see
> > > > > > > https://github.com/espressif/esp-idf/issues/1777.
> > > > > > >
> > > > > > > The questions we have:
> > > > > > > How to enable the "Service Changed Indication"(0x2A05) in the
> > > > > > > bluetooth? Is there any code example in Python?
> > > > > >
> > > > > > If you are registering the services with Bluetoothd then it should
> > > > > > generate the service change automatically:
> > > > > >
> > > > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1185
> > > > > >
> > > > > > When a new service is registered it is indicated here:
> > > > > >
> > > > > > https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/src/gatt-database.c#n1452
> > > > > >
> > > > > >
> > > > > > --
> > > > > > Luiz Augusto von Dentz
> > > >
> > > >
> > > >
> > > > --
> > > > Luiz Augusto von Dentz

[-- Attachment #2: btmon_notify.log --]
[-- Type: application/octet-stream, Size: 12288 bytes --]

Bluetooth monitor ver 5.48
= Note: Linux version 4.19.35-g92e18fefc77 (armv7l)                    0.809169
= Note: Bluetooth subsystem version 2.22                               0.809182
= New Index: 00:16:A4:4A:2D:27 (Primary,UART,hci0)              [hci0] 0.809187
= Open Index: 00:16:A4:4A:2D:27                                 [hci0] 0.809190
= Index Info: 00:16:A4:4.. (Cypress Semiconductor Corporation)  [hci0] 0.809194
@ MGMT Open: bluetoothd (privileged) version 1.14             {0x0002} 0.809200
@ MGMT Open: bluetoothd (privileged) version 1.14             {0x0001} 0.809203
@ MGMT Open: btmon (privileged) version 1.14                  {0x0003} 0.809276
> ACL Data RX: Handle 65 flags 0x02 dlen 8                   #1 [hci0] 4.543721
      ATT: Handle Value Notification (0x1b) len 3
        Handle: 0x0016
          Data: 64
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #2 [hci0] 6.883753
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0001-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 30                  #3 [hci0] 6.884412
      ATT: Read By Group Type Response (0x11) len 25
        Attribute data length: 6
        Attribute group list: 4 entries
        Handle range: 0x0001-0x0005
        UUID: Generic Access Profile (0x1800)
        Handle range: 0x0006-0x0009
        UUID: Generic Attribute Profile (0x1801)
        Handle range: 0x0234-0x023c
        UUID: Heart Rate (0x180d)
        Handle range: 0x023d-0x0240
        UUID: Battery Service (0x180f)
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #4 [hci0] 6.944638
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0241-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 26                  #5 [hci0] 6.945293
      ATT: Read By Group Type Response (0x11) len 21
        Attribute data length: 20
        Attribute group list: 1 entry
        Handle range: 0x0241-0x0250
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef0)
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #6 [hci0] 7.004723
      ATT: Read By Group Type Request (0x10) len 6
        Handle range: 0x0251-0xffff
        Attribute group type: Primary Service (0x2800)
< ACL Data TX: Handle 65 flags 0x00 dlen 9                   #7 [hci0] 7.005369
      ATT: Error Response (0x01) len 4
        Read By Group Type Request (0x10)
        Handle: 0x0251
        Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5       #8 [hci0] 7.005549
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 11                  #9 [hci0] 7.064450
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0234-0x023c
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 27                 #10 [hci0] 7.065112
      ATT: Read By Type Response (0x09) len 22
        Attribute data length: 7
        Attribute data list: 3 entries
        Handle: 0x0235
        Value: 123602372a
        Handle: 0x0238
        Value: 123902382a
        Handle: 0x023b
        Value: 083c02392a
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #11 [hci0] 7.124428
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x023d-0x0240
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 13                 #12 [hci0] 7.125226
      ATT: Read By Type Response (0x09) len 8
        Attribute data length: 7
        Attribute data list: 1 entry
        Handle: 0x023e
        Value: 123f02192a
> HCI Event: Number of Completed Packets (0x13) plen 5      #13 [hci0] 7.125376
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #14 [hci0] 7.184416
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x0241-0x0250
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 69                 #15 [hci0] 7.185101
      ATT: Read By Type Response (0x09) len 64
        Attribute data length: 21
        Attribute data list: 3 entries
        Handle: 0x0242
        Value: 8a4302f1debc9a785634127856341278563412
        Handle: 0x0247
        Value: 8a4802f3debc9a785634127856341278563412
        Handle: 0x024c
        Value: 8a4d02f5debc9a785634127856341278563412
> ACL Data RX: Handle 65 flags 0x02 dlen 11                 #16 [hci0] 7.244526
      ATT: Read By Type Request (0x08) len 6
        Handle range: 0x024e-0x0250
        Attribute type: Characteristic (0x2803)
< ACL Data TX: Handle 65 flags 0x00 dlen 9                  #17 [hci0] 7.246144
      ATT: Error Response (0x01) len 4
        Read By Type Request (0x08)
        Handle: 0x024e
        Error: Attribute Not Found (0x0a)
> HCI Event: Number of Completed Packets (0x13) plen 5      #18 [hci0] 7.246564
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #19 [hci0] 7.304500
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0237-0x0237
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #20 [hci0] 7.305951
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0237
        UUID: Client Characteristic Configuration (0x2902)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #21 [hci0] 7.364540
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x023a-0x023a
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #22 [hci0] 7.366242
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x023a
        UUID: Client Characteristic Configuration (0x2902)
> HCI Event: Number of Completed Packets (0x13) plen 5      #23 [hci0] 7.366660
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #24 [hci0] 7.424617
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0240-0x0240
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #25 [hci0] 7.426085
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0240
        UUID: Client Characteristic Configuration (0x2902)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #26 [hci0] 7.484523
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0244-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #27 [hci0] 7.486104
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0244
        UUID: Characteristic Extended Properties (0x2900)
> HCI Event: Number of Completed Packets (0x13) plen 5      #28 [hci0] 7.486520
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #29 [hci0] 7.544546
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0245-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #30 [hci0] 7.546011
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x0245
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef2)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #31 [hci0] 7.604713
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0246-0x0246
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #32 [hci0] 7.606323
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0246
        UUID: Characteristic User Description (0x2901)
> HCI Event: Number of Completed Packets (0x13) plen 5      #33 [hci0] 7.606747
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #34 [hci0] 7.664243
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0249-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #35 [hci0] 7.665862
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0249
        UUID: Characteristic Extended Properties (0x2900)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #36 [hci0] 7.724603
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024a-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #37 [hci0] 7.726315
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x024a
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef4)
> HCI Event: Number of Completed Packets (0x13) plen 5      #38 [hci0] 7.726625
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #39 [hci0] 7.784545
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024b-0x024b
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #40 [hci0] 7.785996
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x024b
        UUID: Characteristic User Description (0x2901)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #41 [hci0] 7.844187
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024e-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #42 [hci0] 7.845777
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x024e
        UUID: Characteristic Extended Properties (0x2900)
> HCI Event: Number of Completed Packets (0x13) plen 5      #43 [hci0] 7.846215
        Num handles: 1
        Handle: 65
        Count: 2
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #44 [hci0] 7.904466
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x024f-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 24                 #45 [hci0] 7.906160
      ATT: Find Information Response (0x05) len 19
        Format: UUID-128 (0x02)
        Handle: 0x024f
        UUID: Vendor specific (12345678-1234-5678-1234-56789abcdef6)
> ACL Data RX: Handle 65 flags 0x02 dlen 9                  #46 [hci0] 7.964493
      ATT: Find Information Request (0x04) len 4
        Handle range: 0x0250-0x0250
< ACL Data TX: Handle 65 flags 0x00 dlen 10                 #47 [hci0] 7.966067
      ATT: Find Information Response (0x05) len 5
        Format: UUID-16 (0x01)
        Handle: 0x0250
        UUID: Characteristic User Description (0x2901)
> HCI Event: Number of Completed Packets (0x13) plen 5      #48 [hci0] 7.966489
        Num handles: 1
        Handle: 65
        Count: 2
> HCI Event: Number of Completed Packets (0x13) plen 5      #49 [hci0] 8.203559
        Num handles: 1
        Handle: 65
        Count: 1
> ACL Data RX: Handle 65 flags 0x02 dlen 7                 #50 [hci0] 11.833674
      ATT: Read Request (0x0a) len 2
        Handle: 0x0236
< ACL Data TX: Handle 65 flags 0x00 dlen 7                 #51 [hci0] 11.840770
      ATT: Read Response (0x0b) len 2
        Value: 0663
> HCI Event: Number of Completed Packets (0x13) plen 5     #52 [hci0] 12.078687
        Num handles: 1
        Handle: 65
        Count: 1
> ACL Data RX: Handle 65 flags 0x02 dlen 9                 #53 [hci0] 14.055212
      ATT: Write Request (0x12) len 4
        Handle: 0x0237
          Data: 0100
< ACL Data TX: Handle 65 flags 0x00 dlen 5                 #54 [hci0] 14.056230
      ATT: Write Response (0x13) len 0
> HCI Event: Number of Completed Packets (0x13) plen 5     #55 [hci0] 14.329045
        Num handles: 1
        Handle: 65
        Count: 1
< ACL Data TX: Handle 65 flags 0x00 dlen 11                #56 [hci0] 15.078671
      ATT: Handle Value Notification (0x1b) len 6
        Handle: 0x0236
          Data: 0e750000
> HCI Event: Number of Completed Packets (0x13) plen 5     #57 [hci0] 15.330353
        Num handles: 1
        Handle: 65
        Count: 1
< ACL Data TX: Handle 65 flags 0x00 dlen 9                 #58 [hci0] 16.071839
      ATT: Handle Value Notification (0x1b) len 4
        Handle: 0x0236
          Data: 066e
> ACL Data RX: H

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

end of thread, other threads:[~2021-01-28 20:02 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-24  8:42 How to add "Service Changed Indication" Kenny Bian
2021-01-25  3:35 ` Luiz Augusto von Dentz
2021-01-25  6:41   ` Kenny Bian
2021-01-25 17:58     ` Luiz Augusto von Dentz
2021-01-27  8:42       ` Kenny Bian
2021-01-27  8:46         ` Kenny Bian
2021-01-27  8:50           ` Kenny Bian
2021-01-28 19:48             ` Kenny Bian

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.