sputnikdev / eclipse-smarthome-bluetooth-binding

Eclipse SmartHome Bluetooth Binding
46 stars 10 forks source link

Custom Device Profile #59

Open enzian opened 5 years ago

enzian commented 5 years ago

I created my own BLE device based on an nRF52832. It is getting discovered by the binding and the characteristic is read from the device. The characteristic is one byte long. Though the device is discovered and the characteristic can be read - I cannot write the characteristic? Is writing characteristics supported? I can discover, connect and write the characteristic using bluetoothctl...

vkolotov commented 5 years ago

Hi @enzian, thanks for reporting it. Yes, it is supported (but less tested than anything else). Obviously you need to be connected to do so. How do you try to write data with the binding? Is there any errors in the logs?

enzian commented 5 years ago

hey @vkolotov, the value of the characteristic shows up as a space-separated byte array that I then change (from [00] to [01]) screenshot In the logs - I cannot see any errors so far!

vkolotov commented 5 years ago

Strange. Have you enabled debug logging in karaf console?

openhab> log:set DEBUG org.sputnikdev.bluetooth.manager.impl

This definitely should work. BTW, I've got a couple of nRF51822 devices that I use to test the binding and its customisation capability. You can define XMG GATT files for your device so that the binding will use checkboxes to control your boolean characteristic like you have. Here is an example: https://github.com/sputnikdev/eclipse-smarthome-bluetooth-binding/blob/master/gatt-extensions.md

You could come up with something like that:

?xml version="1.0" encoding="UTF-8"?><!-- Copyright 2011 Bluetooth SIG, Inc. All rights reserved. -->
<Characteristic xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/characteristic.xsd"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                type="org.vlad.characteristic.smart_lock_control_point" name="Smart Lock Control Point"
                uuid="DDA3">
    <InformativeText></InformativeText>
    <Value>
        <Field name="Smart Lock Control Point">
            <Requirement>Mandatory</Requirement>
            <Format>8bit</Format>
            <Enumerations>
                <Enumeration key="1" value="Unlock"/>
                <Enumeration key="2" value="Lock"/>
                <ReservedForFutureUse start="3" end="255"/>
            </Enumerations>
        </Field>
    </Value>
</Characteristic>

and


<?xml version="1.0" encoding="utf-8"?><!-- Copyright 2011 Bluetooth SIG, Inc. All rights reserved. -->
<Characteristic xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/characteristic.xsd"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="org.vlad.characteristic.smart_lock_door_status"
                name="Door Status" uuid="DDA1">
    <InformativeText>
        <Abstract>
            Door status.
        </Abstract>
        <Summary>
            Door status.
        </Summary>
    </InformativeText>
    <Value>
        <Field name="Status">
            <InformativeText>Door status
            </InformativeText>
            <Requirement>Mandatory</Requirement>
            <Format>boolean</Format>
            <Enumerations>
                <Enumeration key="0" value="Open"/>
                <Enumeration key="1" value="Closed"/>
            </Enumerations>
        </Field>
    </Value>
</Characteristic>

Let me know how it goes, I'll be supporting you in that.

enzian commented 5 years ago

ok first, the logs:

018-08-15 12:16:34.026 [DEBUG] [ager.impl.CombinedDeviceGovernorImpl] - Updating connection target: /XX:XX:XX:XX:XX:XX/E7:F0:CC:F2:49:55 : true
2018-08-15 12:16:34.239 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Transport [tinyb] reported 1 discovered adapters
2018-08-15 12:16:34.261 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Transport [tinyb] reported 1 discovered devices
2018-08-15 12:16:34.262 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Notifying device discovery listeners (discovered): [Device] tinyb://60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55 [IRIGATION] : 1
2018-08-15 12:16:34.262 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Lost: 0; New: 0; Rediscovered: 1; Stale: 0
2018-08-15 12:16:34.810 [DEBUG] [impl.AbstractBluetoothObjectGovernor] - Interacting with native object (isPowered): /60:6D:C7:C6:B4:06 / 10f342c
2018-08-15 12:16:34.810 [DEBUG] [impl.AbstractBluetoothObjectGovernor] - Interacting with native object (isConnected): /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55 / 4f2a8880
2018-08-15 12:16:34.810 [DEBUG] [ooth.manager.impl.DeviceGovernorImpl] - Checking if device is still alive by getting its RSSI: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55
2018-08-15 12:16:34.811 [DEBUG] [impl.AbstractBluetoothObjectGovernor] - Interacting with native object (getRSSI): /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55 / 4f2a8880
2018-08-15 12:16:35.292 [DEBUG] [ooth.manager.impl.DeviceGovernorImpl] - Services resolved (notification): /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55 : false
2018-08-15 12:16:35.292 [DEBUG] [ooth.manager.impl.DeviceGovernorImpl] - Connected (notification): /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55 : false
2018-08-15 12:16:35.293 [DEBUG] [ooth.manager.impl.DeviceGovernorImpl] - Notifying device governor listener (connected): /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55 : 1 : false
2018-08-15 12:16:35.293 [DEBUG] [ooth.manager.impl.DeviceGovernorImpl] - Resetting characteristic governors due to services unresolved event: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55
2018-08-15 12:16:35.293 [DEBUG] [ager.impl.CombinedDeviceGovernorImpl] - Setting connected: /XX:XX:XX:XX:XX:XX/E7:F0:CC:F2:49:55 : true / false
2018-08-15 12:16:35.293 [DEBUG] [ooth.manager.impl.DeviceGovernorImpl] - Resetting device governor characteristics: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55
2018-08-15 12:16:35.293 [DEBUG] [ooth.manager.impl.DeviceGovernorImpl] - Resetting device governor characteristics: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55
2018-08-15 12:16:35.294 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Resetting governor: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.294 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Resetting governor: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.295 [DEBUG] [ager.impl.CharacteristicGovernorImpl] - Resetting characteristic governor: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.295 [DEBUG] [ager.impl.CharacteristicGovernorImpl] - Resetting characteristic governor: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.296 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Notifying manager listeners (governor ready): 1 : false
2018-08-15 12:16:35.296 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Trying to find object factory: tinyb://60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.297 [DEBUG] [ager.impl.CharacteristicGovernorImpl] - Error occurred while resetting characteristic: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66 : GDBus.Error:org.bluez.Error.Failed: No notify session started 
2018-08-15 12:16:35.297 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Trying to find object factory: tinyb://60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.298 [DEBUG] [th.manager.impl.BluetoothManagerImpl] - Notifying manager listeners (governor ready): 1 : false
2018-08-15 12:16:35.301 [DEBUG] [impl.AbstractBluetoothObjectGovernor] - Governor has been reset: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.301 [DEBUG] [impl.AbstractBluetoothObjectGovernor] - Governor has been reset: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.302 [DEBUG] [ooth.manager.impl.DeviceGovernorImpl] - Notifying device governor listener (services unresolved): /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55 : 1
2018-08-15 12:16:35.303 [DEBUG] [ager.impl.CombinedDeviceGovernorImpl] - Services unresolved (listener): /XX:XX:XX:XX:XX:XX/E7:F0:CC:F2:49:55
2018-08-15 12:16:35.605 [DEBUG] [l.CombinedCharacteristicGovernorImpl] - Updating combined characteristic governor: /XX:XX:XX:XX:XX:XX/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
2018-08-15 12:16:35.606 [DEBUG] [l.CombinedCharacteristicGovernorImpl] - Combined characteristic governor update completed: /XX:XX:XX:XX:XX:XX/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66

I think the most interesting line here is:

2018-08-15 12:16:35.297 [DEBUG] [ager.impl.CharacteristicGovernorImpl] - Error occurred while resetting characteristic: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55/5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66/5a2d40ee-f0bc-11e5-9ce9-5e5517507e66 : GDBus.Error:org.bluez.Error.Failed: No notify session started 

about those XML files: Is it enough to just create a single file for a given characteristic or do I have to create one for the service as well? Is the UUID in the XML file the one that corresponds to the characteristics UUID?

vkolotov commented 5 years ago

This piece of logs does not say anything. It seems to me these logs are captured just right after something has happened bad so that BT manager tries to recover (reset device)

enzian commented 5 years ago

ok, so I attached the entire log here: openhab.log

vkolotov commented 5 years ago

about those XML files: Is it enough to just create a single file for a given characteristic or do I have to create one for the service as well? Is the UUID in the XML file the one that corresponds to the characteristics UUID?

Not sure about service definitions, but it is nice to have anyway. Very easy to do, just copy an existing one and adjust it for your needs.'

Yes, that uuid is your characteristic uuid, you may use full 128 bit uuid

enzian commented 5 years ago

so, I wrote a definition as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Characteristic xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/characteristic.xsd"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                type="org.vlad.characteristic.smart_lock_control_point" name="Irigation Uni"
                uuid="5a2d40ee-f0bc-11e5-9ce9-5e5517507e66">
    <InformativeText></InformativeText>
    <Value>
        <Field name="Valve State">
            <Requirement>Mandatory</Requirement>
            <Format>8bit</Format>
            <Enumerations>
                <Enumeration key="0" value="Closed"/>
                <Enumeration key="1" value="Open"/>
                <ReservedForFutureUse start="2" end="255"/>
            </Enumerations>
        </Field>
    </Value>
</Characteristic>

and placed this file (characteristic.irigator.xml) under /home/openhab/ble_profiles/characteristic and the files belong to the openhab user & group! But the characteristic still appears as before ;-)

vkolotov commented 5 years ago

Have you set up the binding to look in your /home/openhab/ble_profiles/characteristic folder as per an article above? Have you restarted openhab?

vkolotov commented 5 years ago

BTW, <Format>8bit</Format> this will not render as checkbox in OH. It must be boolean. You may add a fake field of 7 bit length after that boolean flag (or even just have only one boolean field <- try that first).

You also may want to enable DEBUG level for org.sputnikdev.bluetooth.gattparser logger to see how it loads your definitions.

enzian commented 5 years ago

Ok, here's the logs openhab.log and the characteristic definition:

<?xml version="1.0" encoding="UTF-8"?>
<Characteristic xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/characteristic.xsd"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                type="org.vlad.characteristic.smart_lock_control_point" name="Irigation Uni"
                uuid="5a2d40ee-f0bc-11e5-9ce9-5e5517507e66">
    <InformativeText></InformativeText>
    <Value>
        <Field name="Valve State">
            <Requirement>Mandatory</Requirement>
            <Format>boolean</Format>
        </Field>
    </Value>
</Characteristic>
vkolotov commented 5 years ago

Ok, that characteristic on your nrf device, is it read-write char? What would you expect to see in OH when you write it to 01, 00? Does it support notifications?

enzian commented 5 years ago

so, 00 would be off, 01 would be on

enzian commented 5 years ago

the characteristic is initialized as follows:

GattCharacteristic  characteristic1(service1_valve_char_uuid, chars1_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);

This should allow reading and writing to it I believe...

vkolotov commented 5 years ago

how would it reflect on UI?

Normally you have a control characteristic and a status characteristic. E.g. when you set control to 1 then your device should try to do something like yours should try to actuate a valve, and then when valve state has changed, your device should set the 'state' characteristic to a proper value, then this state characteristic should notify clients that its state has changed. <- that's the normal approach in bluetooth.

enzian commented 5 years ago

Isn't it weired too, that there are absolutely no log from org.sputnikdev.bluetooth.gattparser?!?

enzian commented 5 years ago

hmm, I could change to code to do exactly that, but for now I'd be happy to just write to it ;-) Reading it works absolutely fine!

vkolotov commented 5 years ago

Have a look at DDA3 and DDA1 from the example above. These are control and status chars

vkolotov commented 5 years ago

hmm, I could change to code to do exactly that, but for now I'd be happy to just write to it ;-)

yes, this should work. But I see a lot of this:

2018-08-15 12:43:13.383 [WARN ] [impl.AbstractBluetoothObjectGovernor] - Error occurred while updating governor: /60:6D:C7:C6:B4:06/E7:F0:CC:F2:49:55 / 4463eb4f : GDBus.Error:org.bluez.Error.Failed: Software caused connection abort

Effectively this means that your device or Bluez drops connection. You should see on OH UI that the "Connected" channel constantly changes its state, is this right?

What version of Bluez do you use?

vkolotov commented 5 years ago

GattCharacteristic characteristic1(service1_valve_char_uuid, chars1_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);

Is this mbed OS code?

vkolotov commented 5 years ago

Bluez 5.47 is the most stable version from my observation, as far as I remember I do get a lot of Software caused connection abort with newer versions.

enzian commented 5 years ago

Effectively this means that your device or Bluez drops connection. You should see on OH UI that the "Connected" channel constantly changes its state, is this right?

The the connected state changes constantly!! I was careful to install 5.47:

sudo systemctl status bluetooth 
● bluetooth.service - Bluetooth service
   Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2018-08-15 13:25:23 CEST; 1s ago
     Docs: man:bluetoothd(8)
 Main PID: 23278 (bluetoothd)
   Status: "Running"
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/bluetooth.service
           └─23278 /usr/libexec/bluetooth/bluetoothd --experimental

Aug 15 13:25:22 xps15 systemd[1]: Starting Bluetooth service...
Aug 15 13:25:23 xps15 bluetoothd[23278]: Bluetooth daemon 5.47
Aug 15 13:25:23 xps15 systemd[1]: Started Bluetooth service.
Aug 15 13:25:23 xps15 bluetoothd[23278]: Starting SDP server
Aug 15 13:25:23 xps15 bluetoothd[23278]: Bluetooth management interface 1.14 initialized
Aug 15 13:25:23 xps15 bluetoothd[23278]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSource
Aug 15 13:25:23 xps15 bluetoothd[23278]: Endpoint registered: sender=:1.84 path=/MediaEndpoint/A2DPSink
vkolotov commented 5 years ago

When you use bluetoothctl tool to connect and write characteristic, is it stable? Is there any Software caused connection abort errors?

enzian commented 5 years ago

No even with bleutoothctl the connection is not stable and there are no errors just disconnects. Sometimes it stays connected for quite some time so I can write the characteristic which is actually sent to the device but most of the times the device is disconnected right after connecting...

I think the issue is not in the binding but in the OS' handling of BLE connections... But I do not know where to start looking since I seem to be pretty alone with the problem of disconnecting BLE devices (well considering how many people actually tinker their own BLE devices this makes sense....).

Do you think I could circumvent the problem by using a BlueGiga adapter?

vkolotov commented 5 years ago

Yeah, BlueGiga is more stable.

Are you sure it is not your device? Can you try to use our phone? There are some good apps that allow you to test bt. NRF Toolbox my favourite.

You also can enable verbose Bluez logging. In that file /etc/systemd/system/bluetooth.target.wants/bluetooth.service

ExecStart=/usr/libexec/bluetooth/bluetoothd -dn

add -dn argument, and then restart bluez

vkolotov commented 5 years ago

I've been doing nrf devices as well, it is pretty stable. So don't give up!

enzian commented 5 years ago

It seems that on Android with NRF Toolbox I do not observe this problem at all...

vkolotov commented 5 years ago

Can you please also try to shut down OH and use bluetoothctl? Just want to make sure that the binding is off at the time you do your experiment.

Yeah, unfortunately Bluez sometimes behaves very badly. It might be actually not Bluez but TinyB library, so I want to make sure we exclude all possible links in the chain. So please do bluetoothctl without the binding running. Also please try to enable/disable scan in bluetoothctl and see if makes any difference.

enzian commented 5 years ago

ok, added the -dn flag to bluetoothd:

[NEW] Controller 60:6D:C7:C6:B4:06 BlueZ 5.47 [default]
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller 60:6D:C7:C6:B4:06 Discovering: yes
[NEW] Device E7:F0:CC:F2:49:55 IRIGATION
[bluetooth]# connect E7:F0:CC:F2:49:55
Attempting to connect to E7:F0:CC:F2:49:55
[CHG] Device E7:F0:CC:F2:49:55 Connected: yes
Connection successful
[NEW] Primary Service
    /org/bluez/hci0/dev_E7_F0_CC_F2_49_55/service0008
    00001801-0000-1000-8000-00805f9b34fb
    Generic Attribute Profile
[NEW] Characteristic
    /org/bluez/hci0/dev_E7_F0_CC_F2_49_55/service0008/char0009
    00002a05-0000-1000-8000-00805f9b34fb
    Service Changed
[NEW] Descriptor
    /org/bluez/hci0/dev_E7_F0_CC_F2_49_55/service0008/char0009/desc000b
    00002902-0000-1000-8000-00805f9b34fb
    Client Characteristic Configuration
[NEW] Primary Service
    /org/bluez/hci0/dev_E7_F0_CC_F2_49_55/service000c
    5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66
    Vendor specific
[NEW] Characteristic
    /org/bluez/hci0/dev_E7_F0_CC_F2_49_55/service000c/char000d
    5a2d40ee-f0bc-11e5-9ce9-5e5517507e66
    Vendor specific
[NEW] Characteristic
    /org/bluez/hci0/dev_E7_F0_CC_F2_49_55/service000c/char000f
    5a2d429c-f0bc-11e5-9ce9-5e5517507e66
    Vendor specific
[NEW] Descriptor
    /org/bluez/hci0/dev_E7_F0_CC_F2_49_55/service000c/char000f/desc0011
    00002902-0000-1000-8000-00805f9b34fb
    Client Characteristic Configuration
[CHG] Device E7:F0:CC:F2:49:55 UUIDs: 00001800-0000-1000-8000-00805f9b34fb
[CHG] Device E7:F0:CC:F2:49:55 UUIDs: 00001801-0000-1000-8000-00805f9b34fb
[CHG] Device E7:F0:CC:F2:49:55 UUIDs: 5a2d3bf8-f0bc-11e5-9ce9-5e5517507e66
[CHG] Device E7:F0:CC:F2:49:55 ServicesResolved: yes
[CHG] Device E7:F0:CC:F2:49:55 Appearance: 0x0200
[CHG] Device E7:F0:CC:F2:49:55 ServicesResolved: no
[CHG] Device E7:F0:CC:F2:49:55 Connected: no
[CHG] Device E7:F0:CC:F2:49:55 Alias: IRIGATION

The device still disconnect after opening the connection and discovering services! Here is the code I'm running - but I don't see anything wrong with it so far since it conforms to the samples which expose the same behavior:


#include <BLE_API.h>
#include "Timer.h"

#define DEVICE_NAME          "IRIGATION"
#define TXRX_BUF_LEN         1

#define VALVE_PIN            12
#define DEVICE_ID            0xFF

bool ledOn = false;

BLE                          ble;

// The uuid of service and characteristics
static const uint8_t service1_uuid[]         = {0x5A, 0x2D, 0x3B, 0xF8, 0xF0, 0xBC, 0x11, 0xE5, 0x9C, 0xE9, 0x5E, 0x55, 0x17, 0x50, 0x7E, 0x66};
static const uint8_t service1_chars1_uuid[]  = {0x5A, 0x2D, 0x40, 0xEE, 0xF0, 0xBC, 0x11, 0xE5, 0x9C, 0xE9, 0x5E, 0x55, 0x17, 0x50, 0x7E, 0x66};
static const uint8_t service1_chars2_uuid[]  = {0x5A, 0x2D, 0x42, 0x9C, 0xF0, 0xBC, 0x11, 0xE5, 0x9C, 0xE9, 0x5E, 0x55, 0x17, 0x50, 0x7E, 0x66};
static const uint8_t uart_base_uuid_rev[]    = {0x66, 0x7E, 0x50, 0x17, 0x55, 0x5E, 0xE9, 0x9C, 0xE5, 0x11, 0xBC, 0xF0, 0xF8, 0x3B, 0x2D, 0x5A};

uint8_t chars1_value[TXRX_BUF_LEN] = {0};
uint8_t chars2_value[TXRX_BUF_LEN] = {0};

// Create characteristic and service
GattCharacteristic  characteristic1(service1_chars1_uuid, chars1_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE );
GattCharacteristic  characteristic2(service1_chars2_uuid, chars2_value, 1, TXRX_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
GattCharacteristic *uartChars[] = {&characteristic1, &characteristic2};
GattService         uartService(service1_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));

uint8_t buf[TXRX_BUF_LEN];

void disconnectionCallBack(const Gap::DisconnectionCallbackParams_t *params) {
  ble.startAdvertising();
}

void connectionCallBack(const Gap::ConnectionCallbackParams_t *params) {
  ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), chars2_value, 1, true);
}

void gattServerWriteCallBack(const GattWriteCallbackParams *Handler) {
  uint8_t buf[TXRX_BUF_LEN];
  uint16_t bytesRead, index;
  //Serial.println("Write Handle : ");
  if (Handler->handle == characteristic1.getValueAttribute().getHandle()) {

    ble.readCharacteristicValue(characteristic1.getValueAttribute().getHandle(), buf, &bytesRead);
//    if (bytesRead == 1){
//      if(ledOn){
//        digitalWrite(LED, HIGH);
//        ledOn = false;
//      }
//      else {
//        digitalWrite(LED, LOW);
//        ledOn = true;
//      }
//    }
    if(buf[0] == 0x00){
      digitalWrite(VALVE_PIN, LOW);

      chars2_value[0] = 0x00;
      ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), chars2_value, 1, true);

      ledOn = false;
      digitalWrite(LED, HIGH);
    }
    else if (buf[0] == 0x01) {
      digitalWrite(VALVE_PIN, HIGH);

      chars2_value[0] = 0x01;
      ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), chars2_value, 1, true);

      ledOn = true;
      digitalWrite(LED, LOW);
    }

  }

}

void setup() {
  pinMode(VALVE_PIN, OUTPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH);

  ble.init();
  ble.onDisconnection(disconnectionCallBack);
  ble.onConnection(connectionCallBack);
  ble.onDataWritten(gattServerWriteCallBack);
  // setup adv_data and srp_data
  ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                   (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) - 1);
  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                   (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid_rev));
  // set adv_type
  ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
  // add service
  ble.addService(uartService);
  // set device name
  ble.setDeviceName((const uint8_t *)DEVICE_NAME);
  // set tx power,valid values are -40, -20, -16, -12, -8, -4, 0, 4
  ble.setTxPower(4);
  // set adv_interval, 100ms in multiples of 0.625ms.
  ble.setAdvertisingInterval(160);
  // set adv_timeout, in seconds
  ble.setAdvertisingTimeout(0);
  // set RGB default status
  uint8_t buf[1] = {0x00};
  ble.updateCharacteristicValue(characteristic2.getValueAttribute().getHandle(), buf, 1, true);
  // start advertising
  ble.startAdvertising();
}

void loop() {
  // put your main code here, to run repeatedly:
  ble.waitForEvent();
}
enzian commented 5 years ago

ok tried some other stuff - disables openhab service on my ubuntu installation so it cannot interfere with my bluetooth connection and now I manage to get connected and occasionally even write to a characteristic but then after some time (<1min) it disconnects me again! My suspicion - could ubuntu be trying anything strange here? Because the logs show bonding going wrong that I did not attempt:

Aug 20 20:40:03 xps15 bluetoothd[916]: bluetoothd[916]: src/device.c:gatt_debug() Registered handler for "Service Changed": 1
Aug 20 20:40:03 xps15 bluetoothd[916]: src/device.c:gatt_debug() Registered handler for "Service Changed": 1
Aug 20 20:40:25 xps15 bluetoothd[916]: bluetoothd[916]: src/adapter.c:remove_temp_devices() /org/bluez/hci0
Aug 20 20:40:25 xps15 bluetoothd[916]: src/adapter.c:remove_temp_devices() /org/bluez/hci0
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/adapter.c:dev_disconnected() Device E7:F0:CC:F2:49:55 disconnected, reason 1
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/adapter.c:adapter_remove_connection()
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: plugins/policy.c:disconnect_cb() reason 1
Aug 20 20:40:38 xps15 bluetoothd[916]: src/adapter.c:dev_disconnected() Device E7:F0:CC:F2:49:55 disconnected, reason 1
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/adapter.c:bonding_attempt_complete() hci0 bdaddr E7:F0:CC:F2:49:55 type 2 status 0xe
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/device.c:device_bonding_complete() bonding (nil) status 0x0e
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/device.c:device_bonding_failed() status 14
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/adapter.c:resume_discovery()
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/device.c:att_disconnected_cb()
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/device.c:att_disconnected_cb() Connection timed out (110)
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/service.c:change_state() 0x564381d08e40: device E7:F0:CC:F2:49:55 profile gap-profile state changed: connected -> disconnecting (0)
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/service.c:change_state() 0x564381d08e40: device E7:F0:CC:F2:49:55 profile gap-profile state changed: disconnecting -> disconnected (0)
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/gatt-client.c:btd_gatt_client_disconnected() Device disconnected. Cleaning up.
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: src/device.c:att_disconnected_cb() Automatic connection disabled
Aug 20 20:40:38 xps15 bluetoothd[916]: bluetoothd[916]: attrib/gattrib.c:g_attrib_unref() 0x564381d08d40: g_attrib_unref=0
Aug 20 20:40:38 xps15 bluetoothd[916]: src/adapter.c:adapter_remove_connection()
Aug 20 20:40:38 xps15 bluetoothd[916]: plugins/policy.c:disconnect_cb() reason 1
Aug 20 20:40:38 xps15 bluetoothd[916]: src/adapter.c:bonding_attempt_complete() hci0 bdaddr E7:F0:CC:F2:49:55 type 2 status 0xe
Aug 20 20:40:38 xps15 bluetoothd[916]: src/device.c:device_bonding_complete() bonding (nil) status 0x0e
Aug 20 20:40:38 xps15 bluetoothd[916]: src/device.c:device_bonding_failed() status 14
Aug 20 20:40:38 xps15 bluetoothd[916]: src/adapter.c:resume_discovery()
Aug 20 20:40:38 xps15 bluetoothd[916]: src/device.c:att_disconnected_cb()
Aug 20 20:40:38 xps15 bluetoothd[916]: src/device.c:att_disconnected_cb() Connection timed out (110)
Aug 20 20:40:38 xps15 bluetoothd[916]: src/service.c:change_state() 0x564381d08e40: device E7:F0:CC:F2:49:55 profile gap-profile state changed: connected -> disconnecting (0)
Aug 20 20:40:38 xps15 bluetoothd[916]: src/service.c:change_state() 0x564381d08e40: device E7:F0:CC:F2:49:55 profile gap-profile state changed: disconnecting -> disconnected (0)
Aug 20 20:40:38 xps15 bluetoothd[916]: src/gatt-client.c:btd_gatt_client_disconnected() Device disconnected. Cleaning up.
Aug 20 20:40:38 xps15 bluetoothd[916]: src/device.c:att_disconnected_cb() Automatic connection disabled
Aug 20 20:40:38 xps15 bluetoothd[916]: attrib/gattrib.c:g_attrib_unref() 0x564381d08d40: g_attrib_unref=0
enzian commented 5 years ago

Also I found this when running btmon:

> ACL Data RX: Handle 64 flags 0x02 dlen 5                                       #28 [hci0] 5.128481
      ATT: Write Response (0x13) len 0
> HCI Event: Disconnect Complete (0x05) plen 4                                  #29 [hci0] 65.585255
        Status: Success (0x00)
        Handle: 64
        Reason: Connection Timeout (0x08)
@ MGMT Event: Device Disconnected (0x000c) plen 8                          {0x0003} [hci0] 65.585299
        LE Address: E7:F0:CC:F2:49:55 (Static)
        Reason: Connection timeout (0x01)
@ MGMT Event: Device Disconnected (0x000c) plen 8                          {0x0002} [hci0] 65.585299
        LE Address: E7:F0:CC:F2:49:55 (Static)
        Reason: Connection timeout (0x01)
@ MGMT Event: Device Disconnected (0x000c) plen 8                          {0x0001} [hci0] 65.585299
        LE Address: E7:F0:CC:F2:49:55 (Static)
        Reason: Connection timeout (0x01)

about 60s after connecting - there is the disconnect...

vkolotov commented 5 years ago

that one is very suspicious:

Aug 20 20:40:25 xps15 bluetoothd[916]: src/adapter.c:remove_temp_devices() /org/bluez/hci0

we will need to look into it, probably study bluez code...

enzian commented 5 years ago

this may be interesting: https://bugreports.qt.io/browse/QTBUG-44622

vkolotov commented 5 years ago

Any luck with this @enzian ?

enzian commented 5 years ago

hey, i moved to raspi where I do not observe the disconnect issue at all - currently I'm kinda low on time to work in this! but I'll get back here to report whatever happens ;-)