eclipse-agail / agile-core

Source code repository for agile core components
Eclipse Public License 2.0
7 stars 16 forks source link

"Write without response" BLE characteristic needed #87

Closed aperezeurob closed 6 years ago

aperezeurob commented 6 years ago

We have already integrated the Xiaomi Mi Band 2 wristband into the agile-dev code, and we are able to connect to it and read the battery level. The other characteristics of the wristband (steps, heart rate, etc.) require authentication, so we have to write some BLE characteristics. The problem is that the BLE characteristic that we have to write only allows "Write without response", but it does not allow regular "Write", since it comes disabled.

When we try to write that BLE characteristic through AGILE, we get the following error: "HTTP 405 Method Not Allowed", which is similar to the error obtained with the regular "Write" (char-write-req) using "gatttool" : "Characteristic Write Request failed: Server doesn't support the request received".

But, if we execute the "Write without response" (char-write-cmd) using "gatttool", we succeed to write properly the BLE characteristic. What we need is a new function to "Write without response" in the "Protocol" class of the "agile-dbus-java-interface/src/main/java/org/eclipse/agail/Protocol.java" file, in addition to the existing Write function:

    /**
     * Send data over the protocol to the device
     *
     * TODO: Detail of this method should be discussed
     */
    public void Write(String deviceAddress, Map<String, String> profile, byte[] payload) throws DBusException;

Thanks a lot for your support.

dpap commented 6 years ago

@aperezeurob I'm not sure how you are trying to write to the BLE interface (either directly or through agile-sdk or node-red.

The BLE Protocol driver implements Write(), Read() and NotificationRead() Inside the driver you would need to put in Device#Execute something like this deviceProtocol.Write( device address, characteristic UUID, [byte stream]);

You would then execute the write with the following access curl -X POST http://localhost:8080/api/device//execute/1

If you try to access Device#Execute via agile-sdk there is the following bug https://github.com/Agile-IoT/agile-sdk/issues/53

aperezeurob commented 6 years ago

In the driver that we have implemented for the Mi Band 2 wristband, "MiBand2Device.java", under the folder:

 ~/agile-dev/modules/agile-core/org.eclipse.agail.DeviceFactory/src/main/java/org/eclipse/agail/device/instance/

more specifically within the following function:

 public void Write(String componentName, String payload)

we already call the suggested function, as follows:

 deviceProtocol.Write(address, getCharacteristicValueProfile(componentName), getBytes(payload));

The problem is that this deviceProtocol.Write(...) calls the function:

 public void Write(String deviceAddress, Map<String, String> profile, byte[] payload) throws DBusException;

which is in the file:

 ~/agile-dev/modules/agile-core/agile-dbus-java-interface/src/main/java/org/eclipse/agail/Protocol.java

And this Write of the Protocol class invokes the "Write with response" BLE functionality, which is not enabled in the BLE characteristic that we have to write. Instead, we need to invoke the "Write without response" BLE functionality which is enabled in the Mi Band 2 characteristic that we have to write, but is not supported in the Protocol class provided.

Summarizing, there are two ways to write BLE characteristics:

We only can use the "Write without response" way to write the required characteristic of the Mi Band 2 wristband. But this "Write without response" is not implemented in the Protocol.java class provided in the agile-dbus-java-interface.

aperezeurob commented 6 years ago

Finally, we get to write in the desired Bluetooth characteristic of the Mi Band 2 wristband, invoking the suggested command:

curl -I -X POST "http://localhost:8080/api/device/{deviceId}/execute/{command}" -H "accept: application/json"

But we fail to write that BLE characteristic invoking the Agile-SDK method:

agile.device.execute(deviceId, command) ⇒ Promise

But this is due to the already known bug Agile-IoT/agile-sdk#53.