2018-11-07 00:49:55

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ] doc: Initial Bluetooth Mesh API

This decribes proposed D-Bus based API for Bluetooth Mesh
implementation.
---
doc/mesh-api.txt | 409 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 409 insertions(+)
create mode 100644 doc/mesh-api.txt

diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
new file mode 100644
index 000000000..1c9a5fa3e
--- /dev/null
+++ b/doc/mesh-api.txt
@@ -0,0 +1,409 @@
+BlueZ D-Bus Mesh API description
+********************************
+
+Mesh Network Hierarchy
+======================
+Service org.bluez.mesh1
+Interface org.bluez.mesh1.Network
+Object path /org/bluez/mesh1
+
+Methods:
+ uint64 Join(object provision_agent,
+ array{string} capabilities,
+ array{byte}[16] uuid,
+ array{string} oob_info,
+ uint32 uri_hash,
+ array{byte} composition)
+
+ This is the first method that an application has to call to become
+ a node on a mesh network.
+
+ The provision_agent parameter is the object that implements
+ org.bluez.mesh.ProvisionAgent interface.
+
+ The capabilities parameter is an array of strings with the following
+ allowed values:
+ "blink", "beep", "vibrate", "out-numeric", "out-alpha", "push",
+ "twist", "in-numeric", "in-alpha", "public-oob", "static-oob".
+
+ The uuid parameter is a 16-byte array that contains Device UUID.
+
+ The oob_info parameter is an array of strings with the following
+ allowed values:
+ "other", "uri", "machine-code-2d", "bar-code", "nfc", "number",
+ "string", "on-box", "in-box", "on-paper", "in-manual", "on-device"
+ The array can be empty if oob data is not available.
+
+ The uri_hash parameter is a 4-octet value that contains URI Hash
+ data that is gnnerated as described in Mesh Profile. If no URI is,
+ available, the passed in value shall be zero.
+
+ The composition parameter is a byte array whose layout
+ follows that of the composition data as defined by Mesh Profile
+ specification. The daemon implements Configuration Server model.
+ The composition data array may not include the Configuration Server
+ model id in which case the model id will be implicitly aded by the
+ daemon.
+
+ In case of success, the method returns a 64-bit token. The token
+ must be preserved by the application in order to authenticate itself
+ to the mesh daemon and attach to the network as a mesh node or
+ permanently remove the identity of the mesh node.
+
+ After the successful completion of this method, the application
+ should call Attach() method to obtain access to mesh network.
+ The meshd daemon retains persistent information about the node
+ identified by the token.
+
+ PossibleErrors:
+ org.bluez.mesh1.Error.Failed,
+ org.bluez.mesh1.Error.Canceled,
+ org.bluez.mesh1.Error.InvalidArguments
+ org.bluez.mesh1.Error.Timeout
+
+ void Cancel(void)
+ Cancels an outstanding Join method. Join will return with
+ org.bluez.mesh1.Error.Canceled
+
+ (object node, array{byte, array{(uint16, dict}} configuration) Attach(
+ object app_defined_root, uint64 token)
+
+ After successful Provisioning/Joining (i.e., after the initial
+ successful Join call), this is the first method that an application
+ must call to obtain access to mesh node functionalities.
+ The daemon verifies whether the application is authorized to
+ use this mesh node based on the value of the 64-bit token, which has
+ been assigned to the application when it first joined mesh network.
+
+ The app_defined_root parameter is a D-Bus object root path of the
+ node where child mesh elements have their own objects that implement
+ the org.bluez.mesh.Access interface. The standard DBus.ObjectManager
+ interface must be available on the app_defined_root path. The
+ app_defined_root tree must conform to the naming convention
+ described in the Mesh Application Hierarchy.
+
+ The token parameter is a 64-bit number that has been obtained
+ as a result of successful Join() method call.
+
+ In case of success, the method call returns mesh node object (see
+ Mesh Node Hierarchy section) and current configuration settings.
+ The configuration parameter is an array, where each entry is a
+ configuration per node element:
+ index (byte) - element index
+ array of model configurations:
+ model_id (uint16) - SIG Model Identifier
+ model_config - dictionary with the following keys defined:
+
+ array{uint16} Bindings : Indices of application keys
+ bound to the model
+ uint32 PublicationPeriod : Model publication period in
+ milliseconds
+ uint16 Vendor: a 16-bit Bluetooth-assigned Company
+ Identifier of the vendor as defined by
+ Bluetooth SIG
+
+ PossibleErrors:
+ org.bluez.mesh1.Error.InvalidArguments
+ org.bluez.mesh1.Error.NotFound,
+ org.bluez.mesh1.Error.Failed
+
+ void Leave(uint64 token)
+
+ This removes the configuration information about the mesh node
+ identified by the 64-bit token parameter. The token parameter
+ has been obtained as a result of successful Join() method call.
+
+ PossibleErrors:
+ org.bluez.mesh1.Error.NotFound
+
+Mesh Node Hierarchy
+===================
+Service org.bluez.mesh1
+Interface org.bluez.mesh1.Node
+Object path /org/bluez/mesh1/node<xxxx>
+ where xxxx is a 4-digit hexadecimal number generated by meshd daemon
+
+Methods:
+
+ void Send(object element_path, uint16_t destination, uint16 key_index,
+ array{byte} data)
+
+ This method is used to send a message originated by a local model.
+
+ The element_path parameter is the object path of an element from
+ a collection of the application elements (see Mesh Application
+ Hierarchy section).
+
+ The destination parameter contains the destination address. This
+ destination must be a uint16 to a unicast address, or a well known
+ group address.
+
+ The key_index parameter determines which application key to use for
+ encrypting the message. The key_index must be valid for that
+ element, i.e., the application key must be bound to a model on this
+ element. Otherwise, org.bluez.mesh1.Error.NotAuthorized will be
+ returned.
+
+ The data parameter is an outgoing message to be encypted by the
+ meshd daemon and sent on.
+
+ Possible errors:
+ org.bluez.mesh1.Error.NotAuthorized
+ org.bluez.mesh1.Error.InvalidArguments
+ org.bluez.mesh1.Error.NotFound
+
+ void Publish(object element_path, uint16 model, array{byte} data)
+
+ This method is used to send a publication originated by a local
+ model. If the model does not exist, or it has no publication record,
+ the method returns org.bluez.mesh1.Error.DoesNotExist error.
+
+ The element_path parameter is the object path of an element from
+ a collection of the application elements (see Mesh Application
+ Hierarchy section).
+
+ The model parameter contains a model ID, as defined by the
+ Bluetooth SIG.
+
+ Since only one Publish record may exist per element-model, the
+ destination and key_index are obtained from the Publication
+ record cached by the daemon.
+
+ Possible errors:
+ org.bluez.mesh1.Error.DoesNotExist
+ org.bluez.mesh1.Error.InvalidArguments
+ org.bluez.mesh1.Error.NotFound
+
+ void VendorPublish(object element_path, uint16 vendor, uint16 model_id,
+ array{byte} data)
+
+ This method is used to send a publication originated by a local
+ vendor model. If the model does not exist, or it has no publication
+ record, the method returns org.bluez.mesh1.Error.DoesNotExist error.
+
+ The element_path parameter is the object path of an element from
+ a collection of the application elements (see Mesh Application
+ Hierarchy section).
+
+ The vendor parameter is a 16-bit Bluetooth-assigned Company
+ Identifier.
+
+ The model_id parameter is a 16-bit vendor-assigned Model Identifier.
+
+ Since only one Publish record may exist per element-model, the
+ destination and key_index are obtained from the Publication
+ record cached by the daemon.
+
+ Possible errors:
+ org.bluez.mesh1.Error.DoesNotExist
+ org.bluez.mesh1.Error.InvalidArguments
+ org.bluez.mesh1.Error.NotFound
+
+Properties:
+ dict Features [read-only]
+
+ The following keys are defined:
+ uint16 Friend
+ uint16 LowPower
+ uint16 Proxy
+ uint16 Beaconing
+ with following enumerated values:
+ 0 - feature is disabled
+ 1 - feature is enabled
+ 2 - feature is unsupported
+
+ uint32 SecondsSinceLastHeard [read-only]
+ This property may be read at any time to determine the number of
+ seconds since mesh network layer traffic was last detected on this
+ node's network.
+
+ uint16 unicast [read-only] : Primary unicast address assigned to
+ this node
+
+Mesh Application Hierarchy
+==========================
+Service unique name
+
+An applcation is a collection of elements that host SIG defined and vendor
+specific models. It is expected that an application implements
+org.freedesktop.DBus.ObjectManager interface.
+
+An example mesh application hierarchy may look like this:
+
+ -> /com/example
+ | - org.freedesktop.DBus.ObjectManager
+ | - org.bluez.mesh1.Attention (optional)
+ |
+ -> /com/example/ele00
+ | | - org.bluez.mesh1.Element
+ -> /com/example/ele01
+ | | - org.bluez.mesh1.Element
+ ...
+ -> /com/example/elexx
+ | | - org.bluez.mesh1.Element
+
+Mesh Element Hierarchy
+======================
+Service unique name
+Interface org.bluez.mesh1.Element
+Object path /<app_defined_root>/ele<yy>
+ where yy is a 2-digit zero relative hexadecimal index of the element
+
+Methods:
+
+ void MessageReceived(uint16 source, uint16 key_index, bool subscription,
+ array{byte} data)
+
+ This method is called by meshd daemon when a message arrives
+ addressed to the application.
+
+ The source parameter is unicast address of the remote node-element
+ that sent the message.
+
+ The key_index parameter indicates which application key has been
+ used to decode the incoming message. The same key_index should be
+ used by the application when sending a response to this message
+ (in case a response is expected).
+
+ The subscription parameter is a boolean that is set to true if
+ the message is received as a part of the subscription (i.e., the
+ destination is either a well known group address or a virtual
+ label.
+
+ The data parameter is the incoming message.
+
+ void UpdateModelConfiguration(uint16 model_id, dict config)
+
+ This method is called by meshd daemon when a model's configuration
+ is updated.
+
+ The model_id parameter contains BT SIG Model Identifier.
+
+ The config parameter is a dictionary with the following keys
+ defined:
+
+ array{uint16} Bindings : Indices of application keys
+ bound to the model
+ uint32 PublicationPeriod : Model publication period in
+ milliseconds
+ uint16 Vendor: a 16-bit Bluetooth-assigned Company
+ Identifier of the vendor as defined by
+ Bluetooth SIG
+
+Mesh Attention Hierarchy
+========================
+Service unique name
+Interface org.bluez.mesh1.Attention
+Object path freely definable
+
+This is an optional interface that implements health attention timer.
+
+Methods:
+ void SetTimer(uint8 element_index, uint16 time)
+
+ The element_index parameter is the element's index within the node
+ where the health server model is hosted.
+
+ The time parameter indicates how many seconds the attention state
+ shall be on.
+
+ PossibleErrors:
+ org.bluez.mesh1.Error.NotSupported
+
+ uint16 GetTimer(uint16 element)
+
+ The element parameter is the unicast address within the node
+ where the health server model is hosted.
+
+ Returns the number of seconds for how long the attention action
+ remains staying on.
+
+ PossibleErrors:
+ org.bluez.mesh1.Error.NotSupported
+
+
+Provisioning Agent Hierarchy
+============================
+Service unique name
+Interface org.bluez.mesh1.ProvisionAgent
+Object path freely definable
+
+Methods:
+ array{byte} PrivateKey()
+
+ This method is called during provisioning if the Provisioner
+ has requested Out-Of-Band ECC key exchange. The Private key
+ is returned to the Daemon, and the Public Key is delivered to
+ the remote Provisioner using a method that does not involve
+ the Bluetooth Mesh system. The Private Key returned must be
+ 32 octets in size, or the Provisioning procedure will fail
+ and be canceled.
+
+ This function will only be called if the Provisioner has
+ requested pre-determined keys to be exchanged Out-of-Band,
+ and the local role is Unprovisioned device.
+
+ array{byte} PublicKey()
+
+ This method is called during provisioning if the local device
+ is the Provisioner, and is requestng Out-Of-Band ECC key
+ exchange. The Public key is returned to the Daemon
+ that is the matched pair of the Private key of the remote
+ device. The Public Key returned must be 64 octets in
+ size, or the Provisioning procedure will fail and be canceled.
+
+ This function will only be called if the Provisioner has
+ requested pre-determined keys to be exchanged Out-of-Band,
+ and the local role is Provisioner.
+
+ void DisplayString(string display)
+ This method is called when the Daemon has something important
+ for the Agent to Display, but does not require any additional
+ input locally. For instance: "Enter "ABCDE" on remote device".
+
+ void DisplayNumeric(uint8 type, uint32 number)
+
+ This method is called when the Daemon has something important
+ for the Agent to Display, but does not require any additional
+ input locally. For instance: "Enter 149264 on remote device".
+
+ The type parameter indicates the display method. An enumeration
+ of "Blink", "Beep", "Vibrate", or "OutNumeric".
+
+ The number parameter is the specific value represented by
+ the Prompt.
+
+ uint32 PromptNumeric(uint8 type)
+
+ This method is called when the Daemon has requires the user to
+ enter a 1-9 digit decimal value.
+
+ The type parameter indicates the input method. An enumeration
+ of "Push", "Twist", or "InNumeric".
+
+ This agent should prompt the user for specific input. For instance:
+ "Enter value being displayed by remote device".
+
+ array{byte} PromptStatic(uint8 type)
+
+ This method is called when the Daemon requires a 16 octet
+ byte array, as an Out-of-Band authentication.
+
+ The type parameter indicates the input method. An enumeration
+ of "Static", or "InAlpha".
+
+ The Static data returned must be 16 octets in size, or the
+ Provisioning procedure will fail and be canceled. If input is
+ an InAlpha String, the printable charactors should be left
+ justified, with trailing 0x00 octets filling the remaining bytes.
+
+ void Cancel()
+
+ This method gets called by the daemon to cancel any existing
+ Agent Requests. When called, any pending user input should be
+ canceled.
+
+
+Mesh Provisioner Hierarchy
+==========================
+<TBD>
--
2.17.2



2018-11-08 10:45:07

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH BlueZ] doc: Initial Bluetooth Mesh API

Hi Inga,

At first glance this looks quite good to me, just some cosmetic comments:

> On 7 Nov 2018, at 2.49, Inga Stotland <[email protected]> wrote:
> +Service org.bluez.mesh1

I don’t think we’ve had the habit of versioning well-known bus names so far. Or did you see this somewhere? So I’d just leave away the version here.

> +Interface org.bluez.mesh1.Network

The way the existing interfaces do versioning is to have the version at the very end, so this should be org.bluez.mesh.Network1

> +Object path /org/bluez/mesh1

I don’t think we have the habit of versioning object paths either. They’re anyway (for the most part) irrelevant - it’s the interfaces an object has that defines its type.


> + PossibleErrors:
> + org.bluez.mesh1.Error.Failed,
> + org.bluez.mesh1.Error.Canceled,
> + org.bluez.mesh1.Error.InvalidArguments
> + org.bluez.mesh1.Error.Timeout

We’ve never versioned errors either, or did you see this done somewhere? So just leave it out from here.

> + (object node, array{byte, array{(uint16, dict}} configuration) Attach(
> + object app_defined_root, uint64 token)
>

This is a bit hard to read due to the long & complex return value. I’d suggest doing the line break before “Attatch” (a common C coding-style as well).

> + void Send(object element_path, uint16_t destination, uint16 key_index,
> + array{byte} data)

Minor inconsistency: should be uint16 instead of uint16_t

Johan

2018-11-08 18:46:37

by Stotland, Inga

[permalink] [raw]
Subject: Re: [PATCH BlueZ] doc: Initial Bluetooth Mesh API

Hi Johan,

On Thu, 2018-11-08 at 12:45 +0200, Johan Hedberg wrote:
> Hi Inga,
>
> At first glance this looks quite good to me, just some cosmetic
> comments:
>
> > On 7 Nov 2018, at 2.49, Inga Stotland <[email protected]>
> > wrote:
> > +Service org.bluez.mesh1
>
> I don’t think we’ve had the habit of versioning well-known bus names
> so far. Or did you see this somewhere? So I’d just leave away the
> version here.
>

From D-Bus Api Design Guidelines: (
https://dbus.freedesktop.org/doc/dbus-api-design.html#api-versioning):

"In summary, version numbers should be included in all service names,
interface names and object paths:

com.example.MyService1

com.example.MyService1.InterestingInterface

com.example.MyService1.OtherInterface

/com/example/MyService1/Manager

/com/example/MyService1/OtherObject
"

I chose to do the name versioning based on the official guidelines.
However, if we want to preserve the historical bluez approach, I don't
mind changing it.


> > +Interface org.bluez.mesh1.Network
>
> The way the existing interfaces do versioning is to have the version
> at the very end, so this should be org.bluez.mesh.Network1
>
> > +Object path /org/bluez/mesh1
>
> I don’t think we have the habit of versioning object paths either.
> They’re anyway (for the most part) irrelevant - it’s the interfaces
> an object has that defines its type.
>
>
> > + PossibleErrors:
> > + org.bluez.mesh1.Error.Failed,
> > + org.bluez.mesh1.Error.Canceled,
> > + org.bluez.mesh1.Error.InvalidArguments
> > + org.bluez.mesh1.Error.Timeout
>
> We’ve never versioned errors either, or did you see this done
> somewhere? So just leave it out from here.

So you can see a number of services following the above mentioned D-Bus
API Guidelines by running d-feet: e..g., org.freedesktop.GeoClue2 or
org.freedesktop.UDisks2 or org.fedoraprojectFirewallD1


>
> > + (object node, array{byte, array{(uint16, dict}}
> > configuration) Attach(
> > +
> > object app_defined_root, uint64 token)
> >
>
> This is a bit hard to read due to the long & complex return value.
> I’d suggest doing the line break before “Attatch” (a common C coding-
> style as well).

Agree

>
> > + void Send(object element_path, uint16_t destination,
> > uint16 key_index,
> > + array{b
> > yte} data)
>
> Minor inconsistency: should be uint16 instead of uint16_t

Agree

>
> Johan

Thank you for the review.

Regards,
Inga


Attachments:
smime.p7s (3.19 kB)

2018-11-10 19:50:25

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH BlueZ] doc: Initial Bluetooth Mesh API

Hi Inga,

On Thu, Nov 08, 2018, Stotland, Inga wrote:
> From D-Bus Api Design Guidelines: (
> https://dbus.freedesktop.org/doc/dbus-api-design.html#api-versioning):
>
> "In summary, version numbers should be included in all service names,
> interface names and object paths:
>
> com.example.MyService1
>
> com.example.MyService1.InterestingInterface
>
> com.example.MyService1.OtherInterface
>
> /com/example/MyService1/Manager
>
> /com/example/MyService1/OtherObject
> "
>
> I chose to do the name versioning based on the official guidelines.
> However, if we want to preserve the historical bluez approach, I don't
> mind changing it.

That's a good point you've brought up, however I think we should stick
to consistency within the project in the first place.

Johan

2018-11-11 10:07:11

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH BlueZ] doc: Initial Bluetooth Mesh API

Hi Inga,

>> At first glance this looks quite good to me, just some cosmetic
>> comments:
>>
>>> On 7 Nov 2018, at 2.49, Inga Stotland <[email protected]>
>>> wrote:
>>> +Service org.bluez.mesh1
>>
>> I don’t think we’ve had the habit of versioning well-known bus names
>> so far. Or did you see this somewhere? So I’d just leave away the
>> version here.
>>
>
> From D-Bus Api Design Guidelines: (
> https://dbus.freedesktop.org/doc/dbus-api-design.html#api-versioning):
>
> "In summary, version numbers should be included in all service names,
> interface names and object paths:
>
> com.example.MyService1
>
> com.example.MyService1.InterestingInterface
>
> com.example.MyService1.OtherInterface
>
> /com/example/MyService1/Manager
>
> /com/example/MyService1/OtherObject
> "
>
> I chose to do the name versioning based on the official guidelines.
> However, if we want to preserve the historical bluez approach, I don't
> mind changing it.

so a long time ago, I looked at this and considered it pointless. It a total bloat that serves no practical purpose. Versioning the interface names makes sense since it allows to upgrade an interface and remove method or change its behavior if that would ever be really needed.

Reality is that we will never write a second daemon for version 2 and that is what versioning essentially implies here. Everything is versioned in a manor that service1 and service2 are totally independent. However what is the point in a technology like Bluetooth. 90% of the methods, properties and behaviors will not change. So we are duplicating everything for 10% or less optimization. That just makes no sense.

>>> + PossibleErrors:
>>> + org.bluez.mesh1.Error.Failed,
>>> + org.bluez.mesh1.Error.Canceled,
>>> + org.bluez.mesh1.Error.InvalidArguments
>>> + org.bluez.mesh1.Error.Timeout
>>
>> We’ve never versioned errors either, or did you see this done
>> somewhere? So just leave it out from here.
>
> So you can see a number of services following the above mentioned D-Bus
> API Guidelines by running d-feet: e..g., org.freedesktop.GeoClue2 or
> org.freedesktop.UDisks2 or org.fedoraprojectFirewallD1

Blindly following some recommendations is dangerous and that is what is happening here. It is blindly following or the project is implement in a memory eating language like Python in the first place.

Regards

Marcel