How to integrate an application with Habit Analytics
Last updated
Last updated
Habit Analytics' platform (muzzley) aims at efficiently and effectively connect, in real-time, people and machines, allowing end-users and software programs to establish communication channels and exchange information or actionable requests. It's stated software programs and not devices, because Habit doesn't restrict the ontology used within the established communication channels, although IoT devices are widely supported and the most common integration within Habit.
In order to be able to act as an intervenient in the Habit Analytics platform, 2 things are required:
intervenient credentials, generated by the Habit Analytics platform
Once these requirements are established, the intervenient will be able to (Figure 1):
interact with a RESTful API to setup, manage and access it's own and other intervenients data.
use an MQTT infrastructure to establish real-time communication with other intervenients
There are the following types of intervenients, each with a set of permissions and allowed types of interactions:
user: represents the end-user of the platform
application: represents the software program that interacts with the platform on behalf of the user
device: represents things that the user wishes to interact with and connects directly with the platform
manager: represents the software program that interacts with the platform on behalf of devices hosted in and proxied by the manufacturer cloud
In this tutorial we will focus, mainly, on application.
Having meaningful communication between intervenients means to empower interactions with the type of structured data that allows efficient and effective data analyses.
In order to be able to achieve this level of analysis without restricting the structure of data used, the specification of ontology schemas is mandatory and each communication channel must relate to and uphold a given schema.
This allows data observers to process the metadata associated with the ontology schema, understand the communication between intervenients and produce relevant additional knowledge and higher levels of data abstraction.
Each low-level communication channel is managed by an entity denoted channel. A channel is composed of components and/or properties (Figure 2).
Channels are entities that represent the communication channels opened between intervenients. They are unique and allow the setup, configuration and management of low-level communication channels, regarding access permissions, message schema validation and message routing and broadcasting.
Components are containers that will hold other components and/or properties, with no special characterisation regarding data, just the specification of usage categories. Components are crucial to contextualize and organize properties (like folders in a filesystem).
Properties are the entities that represent data being sent over the communication channels, between intervenients. Properties may represent actions or just storage records. Properties are characterised by a data type, unit system, unit type, usage categories and permission set.
In order to characterize channels, components and properties, tools to specify ontology schemas, denoted specs, are provided.
Specs are schema specifications for channels, components and properties, There are 3 types of specs channel specs, component specs and property specs each one related to each level of the communication channel hierarchy (Figure 3).
Each spec schema may be associated with one or more templates, characterising a given brand, model and manufacturer, denoted channel template (Figure 4).
The channel template entity is composed by the brand name, model, manufacturer, descriptive texts and images. Each channel must be associate to a channel template (Figure 5). The channel is created as an instance of a channel template.
After specs and templates are in place, a channel may be generated based on a channel template. The generated channel will have a hierarchy mirrored from the underlying spec hierarchy. Each channel part may be configured and accessed via the respective topic:
/v3/channels/{channel_id} to access the channel configuration
/v3/channels/{channel_id}/components/{id or namespace} to access the component configuration
/v3/channels/{channel_id}/components/{id or namespace}/property/{id or namespace} to access the property configuration or for engaging in interactions
For instance, given the examples in the above figures, one could send a message to another intervenient by publishing to /v3/channels/be5d4510-94a7-11e7-b1bf-c33cf9be2246/components/thermostat/properties/mode
intervenient: every software program that hold a set of credentials and is able to interact through one of the allowed protocols
user: intervenient that represents the end-user of the platform
application: intervenient that represents the software program that interacts with the platform on behalf of the user
device: intervenient that represents things that the user wishes to interact with and connects directly with the platform
manager: intervenient that represents the software program that interacts with the platform on behalf of devices hosted in and proxied by the manufacturer cloud
channel: representation on the communication channel between two or more intervenients, used to exchange messages matching the underlying ontology schema
component: parts of the intervenients channels, used to organize sets of properties
property: entities that represent data being sent over the communication channels
channel spec: schema specification for a channel
component spec: schema specification for a component
property spec: schema specification for a property
channel template: template for characterising a communication channel for a brand / model / manufacturer
In order to interact with the Habit Analytics API, clients must authenticate using the OAuth 2.0 protocol, in particular the Client credentials flow. This call must be made using the /v3/auth/authorize endpoint, passing pre-generated credentials, called client_id and client_secret.
Other parameters may / must also be provided, being:
response_type, indicating the flow type, in this case client_credentials
scope, indicating the requested permissions, in this case application
redirect_uri, in case the clients needs to be redirect to a hosted callback
state, a value to be passed as part of the authorization result
The response will be populated with, at least, 4 main attributes:
access_token, the actual token to be used in subsequent calls
expires, the validity of the returned tokens
refresh_token, for refreshing this information, before expires is reached
endpoints, an object containing the HTTP and MQTT base URLs assigned to the requesting client
All subsequent calls must be directed to the base URL provided in endpoints.http and an Authorization header must be added to every API call, in the form:
Request (application/json)
Body
Response 200 (application/json)
Parameters
client_id (required, string)
client_secret (required, string)
response_type (required, string)
scope (required, string)
redirect_uri (optional, string)
state (optional, string)
Request (application/json)
Response 307
Headers
Before the expiration timestamp returned in expires, the intervenient should renew the access token by calling /v3/auth/exchange endpoint, passing the refresh_token return by the call to /v3/auth/authorize.
The return will be exactly the same as return by /v3/auth/authorize.
Request (application/json)
Body
Response 200 (application/json)
Parameters
client_id (required, string)
refresh_token (required, string)
grant_type (required, string)
redirect_uri (optional, string)
Request (application/json)
Response 307
Headers
In order to interact with the Habit Analytics API, clients must authenticate using the OAuth 2.0 protocol, in particular the Client credentials flow. This call must be made using the /v3/auth/authorize endpoint, passing pre-generated credentials, called client_id and client_secret.
All subsequent calls must be directed to the base URL provided in endpoints.http and an Authorization header must be added to every API call, in the form:
The response will be populated with:
id, application ID
name, application name
namespace, application namespace
state, the current state of the application
Response 200 (application/json)
The response will be populated with, at least, 5 main attributes:
id, the user ID
name, the user full name
namespace, unique user namespace
state, user state
target_id, application ID
Parameters
fields (optional, string) # ex: id,name,email,mobile,state
page_size (optional, integer) # ex: 20
state (optional, string) # ex: active
order_by (optional, string) # ex: -created
Response 200 (application/json)
The response will be populated with, at least, 5 main attributes:
id, the user ID
name, the user full name
namespace, unique user namespace
state, user state
target_id, application ID
Response 200 (application/json)
The response will be populated with, at least, 5 main attributes:
id, the channel template ID
template.name, the channel template name
template.channelspec_id, the channel spec ID
access, user access mode
channeltemplate_id, channel template ID
Parameters
fields (optional, string) # ex: id,template.name
page_size (optional, integer) # ex: 20
template.state (optional, string) # ex: active
access (optional, string) # ex: public
order_by (optional, string) # ex: -created
Response 200 (application/json)
The response will be populated with, at least, 5 main attributes:
id, the channel template ID
template.name, the channel template name
template.channelspec_id, the channel spec ID
access, user access mode
channeltemplate_id, channel template ID
Response 200 (application/json)
For reading about the MQTT protocol, please, refer to the official documentation
Each intervenient should listen for MQTT messages by subscribing its channels topic. For instance:
if it's an application: /v3/applications/{application_id}/channels/#
Each intervenient should send MQTT messages by publishing to the channel topic, /v3/channels/{channel_id}/components/{namespace}/properties/{namespace}/value
Each intervenient must provide a unique identifier (client_id) as MQTT user and the previously retrieved access_token as a password.
Each message received or sent to the MQTT topic associated with a given property must state the underlying performative. The performative contextualises the receiving intervenient on what to proceed.
Allowed performatives are:
w, that asks the receiving intervenient to change the property value
r, that ask the receiving intervenient for the property value
iw, that informs the receiving intervenient of the property value, as a result of a w performative message
ir, that informs the receiving intervenient of the property value, as a result of a r performative message
Every time the application receives a request to read or write and it is not possible to execute it due to a problem with an external API, a "iw" should be sent back, to the property "access", with the following data: "unreachable".
A list of MQTT clients support several developing languages:
An SDK and python project that can be used as an example of how to make an integration with Habit is available and open source: https://github.com/habitio/manager-sdk-python
PARAMETER
TYPE
DESCRIPTION
client_id
uuid
the client unique identifier, provided by the Habit Analytics Selfcare
client_secret
string
automatically generated hash, provide by the Habit Analytics Selfcare
redirect_uri
uri
URI to be provided to the user-agent as part of a 303 or 307 HTTP response
response_type
string
the OAuth 2.0 flow to be used
scope
string
a comma separated string of permissions to be associated with the token
state
string
a general purpose string that will be forwarded and added to the flow final result
FIELD
TYPE
DESCRIPTION
access_token
string
the token to be used in subsequent calls to the API as part of an HTTP Authorization header
client_id
uuid
the client unique identifier
code
string
an exchange code, for usage with code flow requests
endpoints
object
HTTP and MQTT base URLs assigned to the requesting client
expires
timestamp
the expiration date for the provided tokens
grant_type
string
the type of grant flow used to generate the provided tokens
refresh_token
string
a token used with /v3/auth/exchange to retrieve fresh tokens, without the re-executing the entire flow
scope
array
granted permissions associated with the provided tokens
state
string
general purpose string forwarded by the client in the first flow call
PARAMETER
TYPE
DESCRIPTION
client_id
uuid
the client unique identifier, provided by the Habit Analytics Selfcare
redirect_uri
uri
URI to be provided to the user-agent as part of a 303 or 307 HTTP response
refresh_token
string
the token provided as refresh_token in a previous call to /v3/auth/authorize
grant_type
string
the type of grant flow used to generate the provided tokens
FIELD
TYPE
DESCRIPTION
access_token
string
the token to be used in subsequent calls to the API as part of an HTTP Authorization header
client_id
uuid
the client unique identifier
code
string
an exchange code, for usage with code flow requests
endpoints
object
HTTP and MQTT base URLs assigned to the requesting client
expires
timestamp
the expiration date for the provided tokens
grant_type
string
the type of grant flow used to generate the provided tokens
refresh_token
string
a token used with /v3/auth/exchange to retrieve fresh tokens, without executing the entire flow
scope
array
granted permissions associated with the provided tokens
PARAMETER
TYPE
DESCRIPTION
io
string
The performative, stating what to do with this message
value
any
The property value, structured as specified in the underlying property spec
sender
uuid
The requesting intervenient unique identifier (read-only, no need to instantiate and if instantiate, overwritten by the platform) Same as the X-Client-Id from the webhook calls
on_behalf_of
uuid
The intervenient unique identifier on behalf of the requesting intervenient is sending this message. Typically for access tokens that were acquired through the password flow, that usually apply to the application -> user relation (read-only, no need to instantiate and if instantiate, overwritten by the platform) Same as the X-Owner-Id from the webhook calls
timestamp
timestamp
Timestamp for the moment the message was sent (read-only, no need to instantiate and if instantiate, overwritten by the platform)
Figure 1 - interacting with Muzzley - zoom in
Figure 2 - channel structure - zoom in
Figure 3 - specs and channels - zoom in
Figure 4 - channel templates - zoom in
Figure 5 - channels as template instances - zoom in