1. Introduction

2. Overview

2.1. What is Live Objects?

Live Objects is a Software as a Service belonging to IoT & Data Analytics services.

Live Objects is a software suite for IoT / M2M solution integrators offering a set of tools to facilitate the interconnection between devices (or connected « things ») and business applications:

  • Connectivity Interfaces (public and private) to collect data, send command or notification from/to IoT/M2M devices,

  • Device Management :inventory, supervision, configuration, resources, campaign management…​,

  • Data Management and collect: Data Storage with Advanced Search features, but also: Message enrichment process, Decoding service and custom pipelines for external enrichment,

  • Message Routing between devices and business applications,

  • Event processing: Alarming with an event detection service by analyzing the data flows sent by devices or occurring on the devices themselves. When these events take place, Live Objects has notification mechanisms to complete the process.

Live Objects overview

Interactive

The public interfaces are reachable from internet. The private interfaces provide interfaces with a specific network (LoRa®).

The SaaS allows multiple tenants on the same instance without possible interactions across tenant accounts (i.e. isolation, for example a device belonging to one tenant could not communicate with a device belonging to an other tenant).

A web portal provides a UI to administration functions like manage the messages and events, supervise your devices and control access to the tenant.

2.2. Architecture

Live Objects SaaS architecture is composed of two complementary layers:

  • Connectivity layer: manages the communications with the client devices and applications,

  • Service layer: various modules supporting the high level functions (device management, data processing and storage, etc.).

Live Objects architecture

Interactive

2.3. Connectivity layer

Live Objects exposes a set of standard and unified public interfaces allowing to connect any programmable devices, gateway or functional IoT backend.

The existing public interfaces are:

MQTT is an industry standard protocol which is designed for efficient exchange of data from and to devices in real-time. It is a binary protocol and MQTT libraries have a small footprint.

HTTPS could be rather used for scarcely connected devices. It does not provide an efficient way to communicate from the SaaS to the devices (requiring periodic polling for example).

For more info, see "Message encodings" section

The public interfaces share a common security scheme based on API keys that you can manage from Live Objects APIs and web portal.

Live Objects is fully integrated with a selection of devices and network. It handles communications from specific families of devices, and translate them as standardized messages available on Live Objects message bus.

The existing private interfaces:

  • LoRa® interface connected with LoRa® network server,

    • to provision LoRa® devices

    • to receive and send data from/to LoRa® devices

Also, it may be possible that your devices are not complient with Live Objects interfaces. It is still possible to use the API for "external connector" feature:

"External connector" mode : a good fit for connect your custom backend who manage your devices and when your devices don’t support Live objects connectivity. This mode has an MQTT API described in mode "External connector".

2.4. Service layer

Behind the connectivity layers for devices, Live Objects is a platform with several, ready to use services to enhanced you IoT potential.

On the one hand, the data collect part with various services: internal enrichment, decoding and custome pipelines for external enrichment services.

On the other hand, these data can be publish into a FIFO and consume using MQTT "application" mode.

  • FIFO : the solution to prevent from message loss in the case of consumer unavailability. Messages are stored in a queue on disk until consumed and acknowledged. When multiple consumers are subscribed to the same queue concurrently, messages are load-balanced between available consumers. More info: FIFO mode,

  • Application mode : a good fit for real-time exchanges between Live Objects backend and your business application. Data messages exchanged are queued in the FIFO queuing bus mechanism mode "Application".

2.4.1. Device management

Live Objects offers various functions dedicated to device operators:

  • supervise devices and manage connectivity,

  • manage devices configuration parameters,

  • send command to devices and monitor the status of these commands,

  • send resources (any binary file) to devices and monitor the status of this operation.

Live Objects attempts to send command, resources or update the parameters on the device as soon as the device is connected and available.

For more info about device and connectivity inventory, see "Device and connectivity inventory" chapter.
For more info about device connectors, see "Device connectors" section.
For more info about device management, see "Device Management" chapter.

2.4.2. Data management

2.4.2.1. Data transformation

Live Objects can transform the published messages by using data enrichment, message decoding and external datamessage transformation by using custom pipelines.

For more info, see "Data transformation" chapter.

2.4.2.3. Data analysis and display

Live Objects allows to store the collected data from any connectivity interfaces. These data could be then retrieved by using HTTPS REST interface.

A full-text search engine based on Elastic search is provided in order to analyze the data stored. This service is accessible through HTTPS REST interface.

For more info, see "Data analysis" chapter.

2.4.3. Messages and Events Processing

2.4.3.1. SEP, SP and AP

Simple event processing service is aimed at detecting notable single event from the flow of data messages.

Based on processing rules that you define, it generates fired events that your business application can consume to initiate downstream action(s) like alarming, execute a business process, etc.

For more info, see "Simple Event Processing" section.

In the other hand, Live Objects allows to process the Activity processing (AP) service which aims at detecting devices that have no activity.

For more info, see "•Activity processing" section.

The State processing (SP) service aims at detecting changes in "device state" computed from data messages.

For more info, see "•State processing" section.

2.4.3.2. Routing and Alarming

The FIFO mode communication is based on the usage of topics to publish a messages with ensuring no message loss. It can forward or route messages to recipients without loss using FIFO Publication and FIFO subscription. You can also use the HTTP push forwarding after the message is processed by event processing service or message routing service. Those services give a notifications or give an alarm to the recipients on purpose.

2.5. Access control

2.5.1. API keys

API keys are used to control the access to the SaaS for devices/application and users to authenticate. You must create an API key to use the API.

For more info, see "API key" and "Role" chapters.

2.5.2. Users management

When an account is created, a user with administration priviledges is also created on the account. This administrator can add other users to the account and set their priviledges. These priviledges are defined by a set of roles. The users can connect to the Live Objects web portal.

2.6. Edge computing

In an advanced usage, you have some ways to integrate the IOT edge plateform wich can collect, manage and store the business data. But more use cases need treatments close to devices to provide :

  • Local treatment with low latency and independency

  • interoperability with industrial protocols

  • Secure approach with keeping locally the business and critical data

3. Getting started

This chapter is a step-by-step manual for beginners with Live Objects giving instructions covering the basic use cases of the service. Here is a small process to begining with Live objects and help you to easy building a use case and end-to-end test.

  • If you have device you can starting to use it.

  • If you do not have a device, browse the instructions in this guide to build a usage that uses only simulators to replace a device. You can use your own device simulator and use MQTT or COAP protocol to connect your virtual device to Live Objects.

Requirements : the data message sent by device (or simulator) must respect the Live Objects data model.

Connect your device and retrieve data with Live Objects (steps by device category and connectivity)

Interactive

3.1. Log in

To log in to Live Objects web portal, connect to liveobjects.orange-business.com using your web-browser:

landing

  • Fill the Sign in form with your credentials:

    • your login,

    • the password set during the activation phase,

  • then click on the Sign in button.

You are redirected to your “Dashboard” page:

landing

3.2. Connect and test your LoRa® device

LoRa® devices need to be registered on Live Objects to send messages.

To quick register your LoRa® device, use the Live Objects portal, liveobjects.orange-business.com.

3.2.1. Register your device

To register a LoRa® device, go to the Devices menu, select LoRa® in the list and click on Add device.

In the form, select the profile that corresponds to your device. If you do not know, select Generic_classA_RX2SF12. Enter your device’s DevEUI, AppEUI and AppKey. Depending on the LoRa® device you are using, these parameters are pre configured and they should come with the device, or you can configure the device resource with your own parameters. Then click on Register.

You can see your device in the Devices menu.

3.2.2. Connect your LoRa® device

When the device is registred then join LoRa® network and it would automatically connected to Live Objects. The device is now ready to send uplink data and begining to publish the data messages.

When you prefer using an API, see Register a LoRa® device

3.3. Simulating an MQTT device

To make a device or an application communicate with Live Objects using MQTT, you will need an API key.

3.3.1. Create an API key

To create an API key, go to the Configuration menu, click on Api keys in the left menu and create a new API key. Select at least the role "DEVICE_ACCESS".

landing

As a security measure, you can not retrieve the API key again after you have closed the API key creation results page. So, note it down to work with the MQTT client, during the scope of this getting started.

landing

3.3.2. Download your simulator tool

It is up to you to choose your favorite MQTT client or library. We will use here MQTT.Fx client. This client is available on Win/MacOSX/Linux and is free. Download and install the last version of MQTT.fx.

3.3.3. Connect your simulator

We will start by creating a new Connection profile and configure it based on the device mode set up.

General panel:

You will configure here the endpoints of Live Objects including authentication information. In this panel, you can set :

landing

Credentials panel:

  • username: json+device : for device mode MQTT connection

  • password: the API key that you just created with the "DEVICE_ACCESS" role

landing

3.3.4. Verify status

We can simulate a device connection to Live Objects with MQTT.fx client by clicking on Connect button of MQTT.fx client.

In Live Objects portal, go to the Devices page, the connected device has "green" status.

landing

3.3.5. Publishing data messages

We will use MQTT.fx client with device mode to send data message as a device would do.

Data message must be published on this topic: dev/data.

Message:

{
    "streamId" : "urn:lo:nsid:sensor:2327398!measures",
    "location": {
        "lat": 48.86667,
        "lon": 2.33333
    },
    "model": "temperatureDevice_v0",
    "value": {
        "status" : "online",
        "tempreature rise frequency" : 10,
        "temp" : 17.25
    },
    "tags": [ "City.NYC", "Model.Prototype" ]
}

With:

  • streamId: the streamId of the message, the message will be forwarded to a topic containing the streamId so an application connected to Live Objects can retrieve messages

  • timestamp: the timestamp of the message, this field is optionnal, if not set by the device, Live Objects will set it with the time of arrival,

  • location: the location of the device, this field is optionnal,

  • model: the model of data contained in the v field, (more about data model)

  • value: the value, this is a free field to store device specific data such as the device sensor values,

  • tags: a list of tags, this field is optionnal.

landing

3.4. Simulating a CoAP\LWM2M device (Beta)

If you want simulate devices that use CoAP\LWM2M2 protocol, you can use a simulator and this section help you to send data to the Live Objects interface by using COAP/LWM2M protocol (to see more about CoAP\LWM2M).

3.5. Device Management basics

3.5.1. Sending a command to a LoRa® device

Messages sent by LoRa® devices to Live Objects are called uplinks. Messages sent by Live Objects to LoRa® devices are called downlinks.

To send a command, go to Devices then select your LoRa® device in the list and go to Downlink tab. Click on Add command, enter a port number between 1 and 223 and enter data in hexadecimal, 0A30F5 for example. The downlink will be sent to your device after the next uplink.

3.5.2. Sending a command to an MQTT device

You must first subscribe to the topic waiting for command "dev/cmd". (Subscribe tab of MQTT.fx)

Go to Devices then select your device in the list and go to Commands tab.

Click on add command then fill the event field with "reboot" then click on Register. The command will appear in MQTT.fx client subscribe tab.

command request

 {
    "req":"reboot",
    "arg":{},
    "cid":94514847
  }

landing

A response can be sent to acknowledge the command received.

To send this response, you can publish a message to this topic "dev/cmd/res". (correlation identifier) must be set with the value received previously.

command response

 {
   "res": {
      "done": true
   },
   "cid": 94514847
 }

Once published, the status of the command will change to "processed" in the portal commands history tab.

A correlation ID uniquely identifies each ‘request’, or the equivalent and used in your intercation with Live Objects API.

3.6. Accessing the stored data

There are several ways to access you device’s data:

  • Going back to Live Objects portal, you can consult the data message that was just stored. Go to Data then search for stream "urn:lo:nsid:dongle:00-14-22-01-23-45!temperature". The data message sent will appear.

landing

  • You can access data from the HTTPS interface.

  • You can perform complex search queries like aggregation using elasticsearch DSL HTTPS interface. See example in See example in Data API chapter

  • Through the MQTT interface, either your configured FIFO queue or your connected MQTT client will receive data messages.

3.7. Connect an application to collect your devices data

3.7.1. Using HTTPS to retrieve your devices' data

Data from you device can be retrived using HTTPS API.

You will need an API key with the DATA_R role. You can create it as you did in the previous part.

The following endpoint enables you to retrieve data from a stream: https://liveobjects.orange-business.com/api/v0/data/streams/{streamId}

Example with a MQTT device:

GET /api/v0/data/streams/urn:lo:nsid:dongle:00-14-22-01-23-45!temperature
Host: https://liveobjects.orange-business.com
Header: X-API-KEY: <a valid API key with DATA_R role>

Example with a LoRa® device:

GET /api/v0/data/streams/urn:lo:nsid:lora:<DevEUI>
Host: https://liveobjects.orange-business.com
Header: X-API-KEY: <a valid API key with DATA_R role>

3.7.2. Using MQTT to retrieve your devices' data

Data published by your devices can be consumed using the MQTT protocol.

You will need an API key with the BUS_R role. You can create it as you did in a previous part.

Then configure a FIFO queues to persist your device’s data until you consume them. To do this, you will have to create a FIFO queue and then route your device’s data to the queue.

In the Data menu, go to the FIFO tab and click on the add a FIFO queue button In the pop-in enter a name myFifo for your FIFO queue, then press Register button: the newly created FIFO queue myFifo is now listed.

landing

The FIFO queue is ready to persist data. To make your device’s data enter the queue, you have to route them to the queue.

In the Data menu, go to the Routing key tab and click on the add a routing key button.

  • enter _~event.v1.data.new.typ.\*.dev.*.con.\*.evt.*.grp.#_ in the "_Routing key filter_" input field, [deprecated]

  • enter ~event.v1.data.new.urn.lora.# in the Routing key filter input field, [deprecated]

  • select myFifo in the Target FIFO select box,

  • press the *Create Binding* button. [deprecated]

Now the binding rules mechanism is deprecated, more information about bindings format in the legacy section Routing Key Filters.
The deprecated topic will be decommissioned in december 2018. Please use the new topic to receive data messages. Please avoid the use of topic event.v1.data.new.#

Future messages sent by your device will be stored in the FIFO queue until an MQTT client subscribes to the queue.

The "application" mode purpose is to retrieve messages available in your FIFOs.

Available MQTT endpoints are described in the section Endpoints.

Beforehand, a connection must be established as follows :

  • clientId: ignored

  • username: application

  • password: a valid Live Objects API key with a BUS_R role

  • willRetain, willQoS, willFlag, willTopic, willMessage: ignored

Then a subscription to the following topic to consume data from your FIFO : "fifo/myFifo".

3.7.3. Tutorial video

3.8. Connect a device without a supported protocols

If you have a fleet of devices that do not support traditional protocols or that are connected to a custom backend, you can use the external connector mode:

  • Connect your specific devices with this mode

  • The external connector which uses the MQTT protocol, allows for all your data to be collected in a single place.

  • Monitor your devices connectivity

  • Configure your devices from Live objects platform

  • Receive command from Live Objects platform

  • Update your devices resource and configuration

4. Account Management and Access Control

4.1. Tenant account

A tenant account is the isolated space on Live Objects dedicated to a specific customer: every interaction between Live Objects and an external actor (user, device, client application, etc.) or registered entities (user accounts, API keys, etc.) is associated with a tenant account.

Live Objects ensures isolation between those accounts: you can’t access the data and entities managed in another tenant account.

Each tenant account is identified by a unique identifier: the tenant ID.

A tenant account also has a name, that should be unique.

4.2. User account

A User Account represents a user identity, that can access the Live Objects web portal.

A user account is identified by a login. A user account is associated with one or many roles. A user can authenticate on the Live Objects web portal using a login and password.

When user authentication request succeeds, a temporary API key is generated and returned, with same roles as the User account.

In case of too many invalid login attempts, the user account is locked out for a while.

For security purpose, a password must be at least 8 characters including at least 1 uppercase letter, 1 lowercase letter, 1 special character, 1 digit and 1 special characters.

4.3. API key

Interactive

A Live Objects API key is a secret that can be used by a device, an application, or a user to authenticate when accessing to Live Objects on the MQTT or HTTPS/REST interfaces. At least one API key must be generated. As a security measure, an API key can not be retrieved after creation (As describe in this section), .

An API key belongs to a tenant account: after authentication, all interactions will be associated only to this account (and thus isolated from other tenant accounts).

An API key can have zero, one or many Roles. These roles allows to restrict the operations that could be performed with the key.

An API key validity can be limited in time.

Creating a tenant account automatically attribute a "master" API key.

That API key is special: it can’t be deleted.

An API key can generate child-API keys that inherit (a subset of) the parent roles and validity period.

An API key can be restrained to one or more message queues:

  • If one or more message queues are selected, the API key can access only these queues.

  • If no message queue is selected, the API key has no restriction and can access any queue.

Thus, the API key can only be used in MQTT access limited to these selected message queues. This for example, makes it possible, after having oriented the right device to the right queue, to restrict access to the data of specific devices.

Usage:

  • In MQTT, clients must connect to Live Objects by using a valid API key value in the password field of the (first) MQTT « CONNECT » packet,

    • In case of unknown API key value, or invalid, the connection is refused.

    • On success, all messages published on this connection will be enriched with the API key id and roles.

  • In HTTPS, clients must specify a valid API key value as HTTP header X-API-Key for every request,

    • In case of unknown API key value, request is refused (HTTP status 403).

    • In case of invalid API key value, request is refused (HTTP status 401).

    • On success, all messages published due to this request will be enriched with the API key id and roles.

4.4. Role

A Role is attributed to an API key or User Account. It defines the privileges on Live Objects. A Role is attributed to an API key or User Account.

Important Notice : Some features are only available if you have subscribed to the corresponding offer, so you may have the proper roles set on your user but no access to some features because these features are not activated on your tenant account (check the tenant offer).

The currently available roles and their inclusion in Admin or User profiles:

Role Name Technical value Admin profile User profile Priviledges

API key

API_KEY_R

X

X

Read parameters and status of an API key.

API key

API_KEY_W

X

X

Create, modify, disable an API key.

User

USER_R

X

X

Read parameters and status of a user.

User

USER_W

X

Create, modify, disable a user.

Settings

SETTINGS_R

X

X

Read the tenant account custom settings.

Settings

SETTINGS_W

X

X

Create, modify tenant account custom settings.

Device

DEVICE_R

X

X

Read parameters and status of a Device mangement.

Device

DEVICE_W

X

Create, modify, disable a Device mangement, send command, modify config, update resource of a Device.

Device Campaign

CAMPAIGN_R

X

X

Read parameters and status of a massive deployment campaign on your Device Fleet.

Device Campaign

CAMPAIGN_W

X

Create, modify a campaign on your Device Fleet.

Data

DATA_R

X

X

Read the data collected by the Store Service or search into this data using the Search Service.

Data

DATA_W

X

Insert a data record to the Store Service. Minimum permission required for the API key of a device pushing data to Live Objects in HTTPS.

Data Processing

DATA_PROCESSING_R

X

X

Read parameters and status of an event processing rule or a Data decoder.

Data Processing

DATA_PROCESSING_W

X

Create, modify, disable an event processing rule or a Data decoder.

Kibana (Beta feature, limited access)

KIBANA_R

X

Access to a Kibana instance running on the Search Service. Requires also DATA_R role to be effective.

Bus Config

BUS_CONFIG_R

X

X

Read config parameters of a FIFO queue or a binding rule.

Bus Config

BUS_CONFIG_W

X

Create, modify a FIFO queue or a binding rule.

Bus Access

BUS_R

X

X

Read data on the Live Objects bus. Minimum permission for the API key of an application collecting data on Live Objects in MQTT(s).

Bus Access

BUS_W

X

X

Publish data on the Live Objects bus.

Bus Access

DEVICE_ACCESS

X

X

Role to set on a Device API key to allow only MQTT Device mode

Bus Access

CONNECTOR_ACCESS

X

X

Role to set on a external connector API key to allow only MQTT external connector mode

Audit Log

LOGS_R

X

X

Read the logs collected by the Audit Log service. This right allows users to use the Audit Log service as debugging tool.

5. Device and connectivity

The version 1 of the device APIs (/api/v1/deviceMgt) comes up with a brand new model of devices in Live Objects.

We have worked on providing unified representations whatever the technology that is used to connect the device to Live Objects using IP connectivity (MQTT, HTTP), LoRa® or SMS, while maintaining the access to each specific technology.

5.1. Principles

A device is a generic term that can designate an equipment (sensor, gateway) or an entity observed by equipments (ex: a building, a car).

5.2. Device description

A device description is a set of JSON documents that store a device identity information, a device state information, a metadata (definition, activity, alias) a device connectivity information for each device that you will connect to Live objects.

Each device description has 2 sections to describe the device representation :

  • Device identity.

  • Device interface representation.

5.2.1. Devices representation

5.2.1.1. Device identifier format

A device identity is represented by a unique identifier. This identifier must respect the following format:

urn:lo:nsid:{ns}:{id}

Where:

  • ns: your device identifier "namespace", used to avoid conflicts between various families of identifier

  • id: your device id
    Should only contain alphanumeric characters (a-z, A-Z, 0-9) and/or any special characters amongst ' ' : - _ | + and must avoid # / !.

5.2.1.2. Device object model

Depending on your connectivity interface, the device object model may have a dedicated "definition" section to describe the parameters of your interface (s).

Device object model overview:

Interactive

Device model in Json format

{
  "id": "urn:lo:nsid:sensor:temp001",
  "name": "mySensor001",
  "description": <<some description>>,
  "defaultDataStreamId": <<myStreamId>>,
  "activityState": <<monitoring the device>>
  "tags": ["Lyon", "Test"],
  "properties" : {
      "manufacturer": <<myManufacturer>>,
      "model": <<myModel>>
  },
  "group": {
      "id": <<id>>,
      "path": <<myPathId>>
  },
  "interfaces": [
        {
          "connector": <<myConnector>>,
          "nodeId": <<interface Id>>,
          "deviceId": "urn:lo:nsid:sensor:temp001",
          "enabled": <<true/false>>,
          "status": <<the status of the interface>>,
          "definition": {
                ........to learn more, see the "Device interface representation" section
          },
          "activity": {},
          "capabilities": {
                "command": {
                   "version" : <<versionNumber>>,
                   "available": <<true/false>>
                },
                "configuration": {
                   "available": <<true/false>>
                },
                "resources": {
                   "available": <<true/false>>
               }
           }
        }
    ],
    "created": <<date>>,
    "updated": <<date>>,
    "staticLocation": {
        "lat": <<Latitude value>>,
        "lon": <<Longitude value>>,
        "alt": <<Altitude value>>
    }
}

Device object model description:

JSON Params Description

id

device unique identifier (Cf. device identifier)

description

Optional. detailed description of the device

name

Optional. name of the device

defaultDataStreamId

default data stream id. Specify the streamId where the data will be store (Cf. "Manage your data stream" section).

tags

Optional. list of additional information used to tag device messages

properties

Optional. map of key/value string pairs detailing device properties

group

group to which the device belongs. The group is defined by its id and its path

interfaces

Optional. list of device network interfaces (Cf. interface object model)

created

creation date of the device

updated

last update date of the device

config

Optional. device configuration

firmwares

Deprecated device firmware versions (same value as "resources", available for compatibily reasons)

resources

Optional. device resource versions

activityState

Optional. device activity state aggregated from the activity processing service, the special state NOT_MONITORED means that the device is not targeted by any activity rule

staticLocation

Optional. the static location of device.

5.2.1.3. Device interface representation

An interface is a platform access. A device can have no, one or several interfaces, which represent different connectivities that the device could use to communicate with Live Objects. Each interface is associated to a protocol managed by Live Objects connector: LoRa®, SMS or MQTT. For the custom protocols, the devices must connected with external connector interface.

devices with single/multi connectivity

Interactive

Interface object model:

JSON Params Description

connector

connector identifier

nodeId

interface unique identifier

deviceId

Optional. device unique identifier

enabled

define if the interface is enabled or disabled

status

interface status

definition

interface definition. The definition depends on connector.

lastContact

Optional. last contact date of the connectivity

activity

interface activity. The activity depends on connector.

capabilities

interface capabilities.

locations

Optional. list of last interface location.

created

registration date of the interface

updated

last update date of the interface

For more information on each connector definition, activity and status, see the appropriate section:

5.2.1.4. Interface status

Each interface has a status field which shows the state of the corresponding interface. The values are the same for all connectors, but each connector sets the status differently. The following table shows which statuses are supported, or will soon be supported by connectors.

Status \ Connector

LoRa®

MQTT

SMS

External connector

REGISTERED

ONLINE

OFFLINE

CONNECTIVITY_ERROR

INITIALIZING

INITIALIZED

REACTIVATED

ACTIVATED

DEACTIVATED

Each interface has an enabled flag which allows or forbids an interface to connect and communicate with Live Objects. The enabled flag changes the interface’s status.

This flag can be set when creating the interface or updating the interface.

The follwing table shows a description of each technical value of the interface status.

Status Value Description

REGISTERED

The device has been registered in the network with the parameters specified when it was created. No uplink data has yet been received by the platform.

INITIALIZING

The network received a Join Request from the device

INITIALIZED

The network sent a Join Accept to the device

ACTIVATED

At least one uplink issued by the device was received by Live Objects (excluding MAC messages)

DEACTIVATED

The device has been deactivated in Live Objects. He can no longer communicate on the network (See the paragraph "Deactivate and reactivate a LoRa® device"

REACTIVATED

The device has been reactivated in Live Objects. Not being able to know a priori the state of the device at the time of the reactivation, the state will pass to "Activated" if a Join Request is received, or directly to "Activated" if an uplink is received.

CONNECTIVITY_ERROR

This status, rare, is displayed in case of problem on configuration of the equipment in the network. If this status appears, contact your support.

ONLINE (MQTT)

The MQTT connection of the device is active

OFFLINE (MQTT)

The device has already connected at least once but its MQTT connection is inactive

ONLINE (SMS)

The SMS device is activated at Live Objects level

OFFLINE (SMS)

The SMS device is deactivated at Live Objects level

5.2.1.5. Capabilities

Capabilities \ Connector

LoRa®

MQTT

SMS

External connector

Command

Configuration

Resource

Interface capabilities represent the Live Objects features compatibility.

  • Command : Compatibility with the generic command engine and API

  • Configuration : Compatibility with config update feature. MQTT connectivity only for now

  • Resource : Compatibility with resource update feature. MQTT connectivity only for now

5.2.1.6. Device static location

The static location is a set of a declared geographical coordinates values (longitude, latitude and altitude). Its section in the device object model must have the following format:

"staticLocation": {
        "lat": <<Latitude value>>,
        "lon": <<Longitude value>>,
        "alt": <<Altitude value>>
    }

This info is useful for stationary devices, or devices that are not sending location information to Live Objects.

This section can be created if setted during device provisioning.
POST /api/v1/deviceMgt/devices/<myDeviceId>
{
    "id": "<myDeviceId>",
    "description": "Device 123",
    "name": "My Device",
    "defaultDataStreamId": "MydefaultStream"
    "interfaces": [
        {
            "connector": "mqtt",
            "enabled": "true",
            "definition": {
                "clientId" : "<myDeviceId>",
                "encoding" : "myEncoding"
            }
        }
    ],
    "staticLocation": {
        "lat": <<Latitude value>>,
        "lon": <<Longitude value>>
    }
}

5.3. Device management basic

5.3.1. Register a device

5.3.1.1. Request

Endpoint:

POST /api/v1/deviceMgt/devices

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Body:

JSON Params Description

id

device unique identifier (Cf. device object model)

tags

Optional. (Cf. device object model)

name

Optional. (Cf. device object model)

description

Optional. (Cf. device object model)

defaultDataStreamId

Optional. (Cf. device object model)

properties

Optional. (Cf. device object model)

group

Optional. (Cf. device object model)

interfaces

Optional. (Cf. device object model)

Devices can be registered with one or more chosen interfaces.

Currently, you can associate an SMS interface (Cf. register device with an SMS interface example) or a LoRa® interface (Cf. register device with a LoRa® interface example) with the devices. The other supported interfaces, the MQTT and External connector interfaces can be automatically registered during the first MQTT connection.

Example: Register a device without interface

POST /api/v1/deviceMgt/devices
{
  "id": "urn:lo:nsid:sensor:temp001",
  "tags": ["Lyon", "Test"],
  "name": "mySensor001",
  "description": "moisture sensor",
  "properties" : {
      "manufacturer": "Orange",
      "model": "MoistureSensorV3"
  },
  "group": {
      "path": "/france/lyon"
  }
}
5.3.1.2. Response

HTTP Code:

200 OK

Body:

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

403

GENERIC_OFFER_DISABLED_ERROR

The requested service is disabled in your offer settings. Please contact a sales representative.

403

GENERIC_ACTION_FORBIDDEN_ERROR

You do not have the required permissions to execute this action.

404

DM_GROUP_NOT_FOUND

Group not found

409

DM_INTERFACE_DUPLICATE

Interface already exists. Conflict on (connector/nodeId)

409

DM_DEVICE_DUPLICATE

Conflict on device id

Example: Register a device without interface

{
    "id": "urn:lo:nsid:sensor:temp001",
    "description": "moisture sensor",
    "name": "mySensor001",
    "defaultDataStreamId": "urn:lo:nsid:sensor:temp001",
    "tags": ["Lyon", "Test"],
    "properties": {
        "manufacturer": "Orange",
        "model": "MoistureSensorV3"
    },
    "group": {
        "id": "sWyaL2",
        "path": "/france/lyon"
    },
    "created": "2018-02-12T13:29:52.442Z",
    "updated": "2018-02-12T13:29:52.442Z"
}

5.3.2. List devices

5.3.2.1. Request

Endpoint:

GET /api/v1/deviceMgt/devices

Query parameters:

Name Description

limit

Optional. maximum number of devices in response. 20 by default.

offset

Optional. the number of entries to skip in the results list. 0 by default.

sort

Optional. sorting selection. Prefix with '-' for descending order. Supported value: id, name, group, created, updated,interfaces.status, interfaces.enabled, interfaces.lastContact. Example: ["urn","-creationTs"]"..

id

Optional. device id

groupPath

Optional. groupPath, Supported filters are → exact match : foo, group or subgroups : foo/*

groupId

Optional. filter list by groupId

name

Optional. device name, Supported filters are → contains : *foo*, end with foo : *foo, start with foo : foo*, exact match : "foo" or foo

tags

Optional. filter list by device tags

connectors

Optional. filter list by interface connector

fields

Optional. fields to return for each device. By default, information returned are id, name, group and tags. Supported value: name, description, group, tags, properties, interfaces, config, firmwares (deprecated), resources, defaultDataStreamId, activityState, created and updated.

interfaces.nodeId

Optional. Filter list by nodeId.

interfaces.status

Optional. Filter list by interface status.

interfaces.enabled

Optional. Filter list by interface enabled state.

property.{filterName}

Optional. Multiple filters, Example: devices?property.temperature=25&property.humidity=58…​

filterQuery

Optional. Device filter expression using RSQL notation. Supported device properties are 'groupPath', 'groupId', 'tags', 'properties'. Supported RSQL operators are '==', '!=', '=in=', '=out=', '=re=', '=lt=', '=le=', '=gt=', '=ge=', 'and', 'or'.

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json
X-Total-Count: <boolean>

For more info about X-Total-Count, see "API v1 paging" section.

Example:

GET /api/v1/deviceMgt/devices?name=mySensor*&sort=-id&fields=name,created,group
5.3.2.2. Response

HTTP Code:

200 OK

Body: List of device object model

JSON Params Description

id

device unique identifier

description

Optional. detailed description of the device

name

Optional. name of the device

defaultDataStreamId

Optional. default data stream Id of the device

tags

Optional. list of device tags

properties

Optional. properties of the device

group

Optional. group to which the device belongs

interfaces

Optional. list of device’s network interfaces

created

Optional. registration date of the device

updated

Optional. last update date of the device

config

Optional. device configuration

firmwares

Deprecated device firmware versions (same value as "resources", available for compatibily reasons)

resources

Optional. device resource versions

activityState

Optional. device activity state aggregated from the activity processing service, the special state NOT_MONITORED means that the device is not targeted by any activity rule

Example:

[
    {
        "id": "urn:lo:nsid:sensor:temp002",
        "name": "mySensor002",
        "group": {
            "id": "root",
            "path": "/"
        },
        "created": "2018-01-08T16:08:39.964Z"
    },
    {
        "id": "urn:lo:nsid:sensor:temp001",
        "name": "mySensor001",
        "group": {
            "id": "sWyaL2",
            "path": "/france/lyon"
        },
        "created": "2018-01-08T16:08:27.259Z"
    }
]

5.3.3. Get a device

5.3.3.1. Request

Endpoint:

GET /api/v1/deviceMgt/devices/<deviceId>

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json

Example:

GET /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001
5.3.3.2. Response

HTTP Code:

*200 OK*

Body:

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

401

UNAUTHORIZED

Authentication failure.

404

DM_DEVICE_NOT_FOUND

Device not found.

Example:

{
    "id": "urn:lo:nsid:sensor:temp001",
    "description": "moisture sensor",
    "name": "mySensor001",
    "defaultDataStreamId": "urn:lo:nsid:sensor:temp001",
    "tags": [
        "france",
        "lyon"
    ],
    "properties": {
        "manufacturer": "Orange",
        "model": "MoistureSensorV3"
    },
    "group": {
        "id": "sWyaL2",
        "path": "/france/lyon"
    },
    "created": "2018-01-08T16:08:27.259Z",
    "updated": "2018-01-08T16:08:27.259Z"
}

5.3.4. Delete device

5.3.4.1. Request

Endpoint:

DELETE /api/v1/deviceMgt/devices/<deviceId>

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json

Example:

DELETE /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001
5.3.4.2. Response

HTTP Code:

204 NO CONTENT

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

404

DM_DEVICE_NOT_FOUND

Device not found

5.4. Device interface management

5.4.1. Add an interface to a registered device

5.4.1.1. Request

Endpoint:

POST /api/v1/deviceMgt/devices/<deviceId>/interfaces

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Body:

JSON Params Description

connector

connector id

enabled

define if the interface is enabled or disabled

definition

interface definition. The definition depends on connector (Cf. SMS interface definition or LoRa® interface definition).

Currently, you can only create an SMS or an LoRa® interface, MQTT interface will be auto-provisionned at the first connection.

Example: Create an SMS interface

POST /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/interfaces
{
    "connector": "sms",
    "enabled": true,
    "definition": {
        "msisdn": "33601201201"
    }
}
5.4.1.2. Response

HTTP Code:

200 OK

Body:

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

403

GENERIC_OFFER_DISABLED_ERROR

The requested service is disabled in your offer settings. Please contact a sales representative.

404

DM_DEVICE_NOT_FOUND

Device not found

404

DM_CONNECTOR_UNAVAILABLE

Connector not found or unavailable

409

DM_INTERFACE_DUPLICATE

Interface already exists. Conflict on (connector/nodeId)

Example:

{
    "connector": "sms",
    "nodeId": "33601201201",
    "deviceId": "urn:lo:nsid:sensor:temp001",
    "enabled": true,
    "status": "ONLINE",
    "definition": {
        "msisdn": "33601201201"
    },
    "activity": {},
    "capabilities": {
        "command": {
            "version" : 1,
            "available": true
        },
        "configuration": {
            "available": false
        },
        "resources": {
            "available": false
        }
    },
    "created": "2018-03-02T15:54:33.943Z",
    "updated": "2018-03-02T15:54:33.943Z"
}

5.4.2. List device interfaces

5.4.2.1. Request

Endpoint:

GET /api/v1/deviceMgt/devices/<deviceId>/interfaces

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json

Example:

GET /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/interfaces
5.4.2.2. Response

HTTP Code:

200 OK

Body:

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

404

DM_DEVICE_NOT_FOUND

Device not found.

Example:

[
  {
    "connector": "sms",
    "nodeId": "33601201201",
    "enabled": true,
    "status": "ONLINE",
    "activity": {},
    "definition" : {
        "msisdn" : "33601201201",
        "serverPhoneNumber" : "12345"
    },
    "capabilities": {
        "command": {
            "version" : 1,
            "available": true
        },
        "configuration": {
            "available": false
        },
        "resources": {
            "available": false
        }
    }
  },
  {
    "connector": "mqtt",
    "nodeId": "urn:lo:nsid:sensor:temp001",
    "enabled": true,
    "status": "ONLINE",
    "lastContact": "2018-03-02T15:57:23.772Z",
    "activity" : {
        "apiKeyId" : "6c2c569d91b5f174f60bd73d",
        "mqttVersion" : 4,
        "mqttUsername" : "json+device",
        "mqttTimeout" : 60,
        "remoteAddress" : "217.0.0.0/44341",
        "lastSessionStartTime" : "2019-07-24T15:09:22.560Z",
        "lastSessionEndTime" : "2019-07-24T16:20:37.333Z",
        "security" : {
            "secured": true,
            "protocol": "TLSv1.2",
            "cipher": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
            "clientCertAuthentication": true,
            "sniHostname": "mqtt.liveobjects.orange-business.com"
        }
    },
    "capabilities": {
        "command": {
            "version" : 1,
            "available": true ("false" if the device is "OFFLINE" or has not suscribed to the topic "dev/cmd")
        },
        "configuration": {
            "version" : 1,
            "available": true ("false" if the device is "OFFLINE" or has not suscribed to the topic "dev/cfg")
        },
        "resources": {
            "version" : 1,
            "available": true ("false" if the device is "OFFLINE" or has not suscribed to the topic "dev/rsc/upd")
        }
    },
    "firmwares" : { (same value as "resources", available for compatibility reasons)
        "MyFW" : "1.0.2"
    },
    "resources" : {
        "MyFW" : "1.0.2"
    }
  }
]

5.4.3. Get interface details

5.4.3.1. Request

Endpoint:

GET /api/v1/deviceMgt/devices/<deviceId>/interfaces/<interfaceId>

The interfaceId must respect the following format {connector}:{nodeId}.

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json

Example:

GET /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/interfaces/sms:33601201201
5.4.3.2. Response

HTTP Code:

200 OK

Body:

Error case:

HTTP Code Error code message

403

GENERIC_OFFER_DISABLED_ERROR

The requested service is disabled in your offer settings. Please contact a sales representative.

404

DM_CONNECTOR_UNAVAILABLE

Connector not found or unavailable

404

DM_INTERFACE_NOT_FOUND

Interface not found

404

DM_DEVICE_NOT_FOUND

Device not found

Example:

{
        "connector": "sms",
        "nodeId": "33601201201",
    "deviceId": "urn:lo:nsid:sensor:temp001",
        "enabled": true,
        "status": "ONLINE",
        "definition": {
            "msisdn": "33601201201"
        },
        "activity": {
            "lastUplink": {
                "timestamp": "2018-03-05T10:43:46.268Z",
                "serverPhoneNumber": "20259"
            }
        },
    "capabilities": {
        "command": {
            "version" : 1,
            "available": true
    },
        "configuration": {
            "available": false
        },
        "resources": {
            "available": false
        }
    },
    "created": "2018-03-05T10:20:06.404Z",
    "updated": "2018-03-05T10:20:06.408Z"
}

5.4.4. Update an interface

5.4.4.1. Request

Endpoint:

PATCH /api/v1/deviceMgt/devices/<deviceId>/interfaces/<interfaceId>

The interfaceId must respect the following format {connector}:{nodeId}.

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Body:

JSON Params Description

deviceId

Optional. new device identifier

enabled

Optional. define if the interface is enabled or disabled

definition

Optional. new interface definition

Example:

PATCH /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/interfaces/sms:33601201201
{
    "deviceId": "urn:lo:nsid:sensor:temp002",
    "enabled": "false",
    "definition": {
        "encoding": "myDecoder"
    }
}
5.4.4.2. Response

HTTP Code:

200 OK

Body:

Error case:

HTTP Code Error code message

404

DM_INTERFACE_NOT_FOUND

Interface not found

404

DM_DEVICE_NOT_FOUND

Device not found

Example:

{
    "connector": "sms",
    "nodeId": "33601201201",
    "deviceId": "urn:lo:nsid:sensor:temp002",
    "enabled": false,
    "status": "ONLINE",
    "definition": {
        "msisdn": "33601201201",
        "encoding": "myDecoder"
    },
    "activity": {
        "lastUplink": {
            "timestamp": "2018-03-05T10:43:46.268Z",
            "serverPhoneNumber": "20259"
        }
    },
    "capabilities": {
        "command": {
            "version" : 1,
            "available": true
        },
        "configuration": {
            "available": false
        },
        "resources": {
            "available": false
        }
    },
    "created": "2018-03-05T10:20:06.404Z",
    "updated": "2018-03-05T13:51:09.312Z"
}

5.4.5. Delete an interface

5.4.5.1. Request

Endpoint:

DELETE /api/v1/deviceMgt/devices/<deviceId>/interfaces/<interfaceId>

The interfaceId must respect the following format {connector}:{nodeId}.

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json

Example:

DELETE /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/interfaces/sms:33601201201
5.4.5.2. Response

HTTP Code:

204 NO CONTENT

Error case:

HTTP Code Error code message

403

GENERIC_OFFER_DISABLED_ERROR

The requested service is disabled in your offer settings. Please contact a sales representative.

404

DM_CONNECTOR_UNAVAILABLE

Connector not found or unavailable

404

DM_INTERFACE_NOT_FOUND

Interface not found

404

DM_DEVICE_NOT_FOUND

Device not found

5.5. Connectivity

5.5.1. LoRa® connector

For information about legacy API (v0), please see API LoRa® legacy section.

5.5.1.1. Definitions

devEUI

The global end-device ID of the interface (for more information, see the chapter 6.2.1 of lora-alliance.org/wp-content/uploads/2020/11/lorawan1.0.3.pdf).

appEUI

The global application ID of the interface (for more information, see the chapter 6.1.2 of lora-alliance.org/wp-content/uploads/2020/11/lorawan1.0.3.pdf).

appKey

The application key of the interface (for more information, see the chapter 6.2.2 of lora-alliance.org/wp-content/uploads/2020/11/lorawan1.0.3.pdf).

activationType

OTAA: Over The Air Activation.

profile

profile of the Interface which represents the Class (A or C). Can be specific for an Interface (ex. LoRaMote devices) or generic (ex. LoRaWAN/DemonstratorClasseA or LoRaWAN/DemonstratorClasseC). Please refer to Orange LoRa® device reference. The API GET Profile allows to have the list of available profiles.

encoding

Optional. encoding type of the binary payload sent by the interface, the decoder must be registered first (Cf. "Decoding service" section).

connectivityOptions

connectivity options used for the interface. Supported options are ackUl and tdoa.

connectivityPlan

connectivity plan to use for the interface.

Example:

{
    "devEUI": "0101010210101010",
    "profile": "Generic_classA_RX2SF9",
    "activationType": "OTAA",
    "appEUI": "9879876546543211",
    "appKey": "11223344556677889988776655443322",
    "connectivityOptions" : {
        "ackUl" : true,
        "tdoa" : false
    },
    "connectivityPlan" : "orange-cs/CP_Basic"
}

Important Notice : Some features are only available if you have subscribed to the corresponding offer, so you may have the rights set on your tenant but no access to some features because these features are not activated on your tenant account (check the tenant offer).

If an option is applied to a device, it will be effective only if the option is allowed for the tenant. If both connectivityOptions and connectivityPlan are set, connectivityPlan will be selected. connectivityPlan should be used preferably at connectivityOptions but at least one of two shall be defined. connectivityPlan could be selected among list returned by the API LIST Connectivity plans .

5.5.1.2. Activity
JSON Params Description

lastActivationTs

Optional. last activation date of the interface

lastDeactivationTs

Optional. last deactivation date of the interface

lastSignalLevel

Optional. last signal level

lastBatteryLevel

Optional. last battery level (for more information, see the chapter 5.5 of lora-alliance.org/wp-content/uploads/2020/11/lorawan1.0.3.pdf).

lastDlFcnt

Optional. last downlink frame counter

lastUlFcnt

Optional. last uplink frame counter

Example:

{
    "activity": {
        "lastActivationTs": "2018-03-19T13:02:13.482Z",
        "lastActivationTs": "2018-03-20T14:10:26.231Z",
        "lastSignalLevel": 5,
        "lastBatteryLevel": 54,
        "lastDlFcnt": 7,
        "lastUlFcnt": 1
    }
}
5.5.1.3. Status

LoRa® supports the following statuses: REGISTERED, INITIALIZING, INITIALIZED, ACTIVATED, DEACTIVATED, REACTIVATED, CONNECTIVITY_ERROR. The following diagram shows how LoRa® connector sets interfaces' status. The consistency check referred in the diagram is an automatic periodic check that verifies the consistency of information between Live Objets and the LoRa® network provider, it can detect potential problems on an LoRa® interface.

Status state machine in LoRa® connector

Interactive

5.5.1.4. Examples
5.5.1.4.1. Register a device with LoRa® interface

For more explanation on device creation, please see Register a device section.

Request:

POST /api/v1/deviceMgt/devices
{
    "id": "urn:lo:nsid:lora:0101010210101010",
    "tags": ["Lyon", "Test"],
    "name": "myLoraSensor",
    "description": "device with LoRa interface",
    "properties" : {
        "manufacturer": "Orange",
        "model": "LoraSensor"
    },
    "interfaces": [
        {
            "connector": "lora",
            "enabled": true,
            "definition": {
                "devEUI": "0101010210101010",
                "profile": "Generic_classA_RX2SF9",
                "activationType": "OTAA",
                "appEUI": "9879876546543211",
                "appKey": "11223344556677889988776655443322",
                "connectivityOptions" : {
                    "ackUl" : true,
                    "tdoa" : false
                },
                "connectivityPlan" : "orange-cs/CP_Basic"
            }
        }
    ],
    "group": {
        "id": "sWyaL2",
        "path": "/france/lyon"
    }
}

Response:

200 OK
{
    "id": "urn:lo:nsid:lora:0101010210101010",
    "name": "myLoraSensor",
    "description": "device with LoRa interface",
    "tags": [
        "Test",
        "Lyon"
    ],
    "properties": {
        "manufacturer": "Orange",
        "model": "LoraSensor"
    },
    "group": {
        "id": "sWyaL2",
        "path": "/france/lyon"
    },
    "interfaces": [
        {
            "connector": "lora",
            "nodeId": "0101010210101010",
            "enabled": true,
            "status": "REGISTERED",
            "definition": {
                "devEUI": "0101010210101010",
                "profile": "Generic_classA_RX2SF9",
                "activationType": "OTAA",
                "appEUI": "9879876546543211",
                "appKey": "11223344556677889988776655443322",
                "connectivityOptions" : {
                    "ackUl" : true,
                    "tdoa" : false
                },
                "connectivityPlan" : "orange-cs/CP_Basic"
            }
        }
    ],
    "defaultDataStreamId": "urn:lo:nsid:lora:0101010210101010",
    "created": "2018-03-06T13:23:37.712Z",
    "updated": "2018-03-06T13:23:37.945Z"
}
5.5.1.4.2. Add a LoRa® interface to a registered device

For more information on interface addition, please see Add a interface section.

Request:

POST /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/interfaces
{
    "connector": "lora",
    "enabled": true,
    "definition": {
        "devEUI": "0202020220202020",
        "profile": "Generic_classA_RX2SF9",
        "activationType": "OTAA",
        "appEUI": "4573876546543211",
        "appKey": "11113344556677889988776655443322",
        "connectivityOptions" : {
            "ackUl" : true,
            "tdoa" : false
        },
        "connectivityPlan" : "orange-cs/CP_Basic"
    }
}

Response:

201 CREATED
{
    "connector": "lora",
    "nodeId": "0202020220202020",
    "deviceId": "urn:lo:nsid:sensor:temp001",
    "enabled": true,
    "status": "REGISTERED",
    "definition": {
        "devEUI": "0202020220202020",
        "activationType": "OTAA",
        "profile": "Generic_classA_RX2SF9",
        "appEUI": "4573876546543211",
        "connectivityPlan" : "orange-cs/CP_Basic"
    },
    "activity": {},
    "created": "2018-03-06T13:37:31.397Z",
    "updated": "2018-03-06T13:37:31.397Z"
}
5.5.1.4.3. List LoRa® connectivity plans

A connectivity plan defines the interface capabilities and parameters that are needed by the network for access service. These information elements shall be provided by the manufacturer.

5.5.1.4.4. Request

Endpoint:

GET /api/v1/deviceMgt/connectors/lora/connectivities

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json
5.5.1.4.5. Response

HTTP Code:

200 OK

Body:

[ {
  "id" : "orange-cs/CP_Basic",
  "name" : "CP_Basic",
  "parameters" : {
    "nbTransMax" : 3,
    "tdoa" : false,
    "ackUl" : false,
    "sfMax" : 12,
    "sfMin" : 7,
    "nbTransMin" : 1
  }
}, {
  "id" : "orange-cs/CP_ACK",
  "name" : "CP_ACK",
  "parameters" : {
    "nbTransMax" : 3,
    "tdoa" : false,
    "ackUl" : true,
    "sfMax" : 12,
    "sfMin" : 7,
    "nbTransMin" : 1
  }
} ]
HTTP Code Error code message

403

4030

Service is disabled. Please contact your sales entry point.

5.5.1.4.6. Get LoRa® interfaces profiles

An interface-profile defines the interface capabilities and boot parameters that are needed by the network for access service. These information elements shall be provided by the manufacturer.

The profile of the interface which represents the Class (A or C). Can be specific for an Interface (ex. LoRaMote devices) or generic (ex. LoRaWAN/DemonstratorClasseA or LoRaWAN/DemonstratorClasseC). Please refer to Orange LoRa® device reference. The API GET profiles allows to have the list of available profiles.

5.5.1.4.7. Request

Endpoint:

GET /api/v1/deviceMgt/connectors/lora/profiles

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json
5.5.1.4.8. Response

HTTP Code:

200 OK

Body:

[ "JRI", "DP_Generic_AS923_ClassA", "ERCOGENER_EG-IoT", "Sensing_Labs_T_IP68", "ESM 5k ELSYS Class A", "NETVOX_R711_AS923_ClassA", "Connit Pulse", "OCEAN_OBR-L", "ATIM Class A", "Adeunis RF Demonstrator_US_915", "DECENTLAB_DLR2-EU868", "DIGITAL_MATTER_EU868"]

Error case:

HTTP Code Error code message

403

4030

Service is disabled. Please contact your sales entry point.

5.5.2. SMS connector

5.5.2.1. Definitions

msisdn

device msisdn

serverPhoneNumber

Optional. server phone number. Must be defined in the offer settings.

encoding

Optional. name of the decoder that will be used to decode received SMSs, the decoder must be registered first (Cf. "Decoding service" section).

{
    "msisdn": "33601201201",
    "serverPhoneNumber": "20259",
    "encoding": "myDecoder"
}
5.5.2.2. Eligible cellular subscriptions for SMS connectivity

To send and receive SMS messages to/from a device using an SMS interface, this device must have a cellular subscription from the following operators :

  • Orange France

  • Orange Poland

  • Orange Romania

  • Orange Slovakia

  • Orange Spain

5.5.2.3. Activity
JSON Params Description

lastUplink

Optional. last uplink date of the interface

lastDownlink

Optional. last downlink date of the interface

lastUplink and lastDownlink have the following format:

JSON Params Description

timestamp

date of the activity

serverPhoneNumber

server phone number used

Example:

{
    "activity": {
      "lastUplink" : {
        "timestamp" : "2020-09-07T14:50:04.352Z",
        "serverPhoneNumber" : "+3320259"
      },
      "lastDownlink" : {
        "timestamp" : "2020-09-07T14:42:24.180Z",
        "serverPhoneNumber" : "20259"
      }
    }
}
5.5.2.4. Status

The SMS connector supports the following statuses describes in interface status. When an SMS interface is created, its status is set to ONLINE and it will not change. When an SMS interface is disabled, its status is set to DEACTIVATED.

5.5.2.5. Examples
5.5.2.5.1. Register a device with an SMS interface

For more information on device creation, please see Register a device section.

Request:

POST /api/v1/deviceMgt/devices
{
    "id": "urn:lo:nsid:sensor:temp002",
    "tags": ["Lyon", "Test"],
    "name": "mySensor002",
    "description": "moisture sensor",
    "properties" : {
        "manufacturer": "Orange",
        "model": "MoistureSensorV3"
    },
    "interfaces": [
        {
            "connector": "sms",
            "enabled": true,
            "definition": {
                "msisdn": "33600000001",
                "serverPhoneNumber" : "20259"
            }
        }
    ],
    "group": {
        "id": "sWyaL2",
        "path": "/france/lyon"
    }
}

Response:

200 OK
{
    "id": "urn:lo:nsid:sensor:temp002",
    "name": "mySensor002",
    "description": "moisture sensor",
    "tags": [
        "Test",
        "Lyon"
    ],
    "properties": {
        "manufacturer": "Orange",
        "model": "MoistureSensorV3"
    },
    "group": {
        "id": "sWyaL2",
        "path": "/france/lyon"
    },
    "interfaces": [
        {
            "connector": "sms",
            "nodeId": "33600000001",
            "enabled": true,
            "status": "ONLINE",
            "definition": {
                "msisdn": "33600000001",
                "serverPhoneNumber" : "20259"
            }
        }
    ],
    "defaultDataStreamId": "urn:lo:nsid:sensor:temp002",
    "created": "2018-03-06T11:30:42.777Z",
    "updated": "2018-03-06T11:30:42.819Z"
}
5.5.2.5.2. Add an SMS interface to a registered device

For more information on interface addition and example with SMS interface, please see Add a interface section.

Request:

POST /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/interfaces
{
    "connector": "sms",
    "enabled": true,
    "definition": {
      "msisdn": "33600000001",
      "serverPhoneNumber" : "20259"
    }
}

Response:

201 CREATED
{
    "connector": "sms",
    "nodeId": "33600000001",
    "deviceId": "urn:lo:nsid:sensor:temp001",
    "enabled": true,
    "status": "ONLINE",
    "definition": {
      "msisdn": "33600000001",
      "serverPhoneNumber" : "20259"
    },
    "activity": {},
    "created": "2018-03-06T13:37:31.397Z",
    "updated": "2018-03-06T13:37:31.397Z"
}

5.5.3. MQTT connector

For information about MQTT interface and messages that your device can send or receive, please refer to the MQTT device mode.

5.5.3.1. Definition

clientId

device clientId used in mqtt MQTT device mode.

encoding

Optional. name of the decoder that will be used to decode data received from this interface. It will override 'metadata.encoding' value from this device’s data messages. The decoder must be registered first (Cf. "Decoding service" section).

{
    "clientId" : "mydevice_001",
    "encoding" : "myEncoding_v1"
}
5.5.3.2. Activity
JSON Params Description

apiKeyId

Optional. id of the API KEY used for the last device connection

mqttVersion

Optional. mqtt version used by the device mqtt client

mqttUsername

Optional. mqtt username used by the device mqtt client

mqttTimeout

Optional. mqtt timeout configured by the device mqtt client

remoteAddress

Optional. public IP address of the device mqtt client

lastSessionStartTime

Optional. last mqtt session start date

lastSessionEndTime

Optional. last mqtt session end date

security

security information

security has the following format:

JSON Params Description

secured

is (or was) a security protocol used

protocol

Optional. security protocol used

cipher

Optional. cipher suite used

clientCertAuthentication

Optional. is (or was) client certificate authentication used

sniHostname

Optional. hostname provided by the Server Name Indication extension

Example:

{
    "activity" : {
      "apiKeyId" : "5de8d14085a455f5c8525655",
      "mqttVersion" : 4,
      "mqttUsername" : "json+device",
      "mqttTimeout" : 60,
      "remoteAddress" : "217.167.1.65/61214",
      "lastSessionStartTime" : "2020-08-18T15:32:33.510Z",
      "lastSessionEndTime" : "2020-08-18T15:48:51.488Z",
      "security" : {
        "secured": true,
        "protocol": "TLSv1.2",
        "cipher": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
        "clientCertAuthentication": true,
        "sniHostname": "mqtt.liveobjects.orange-business.com"
      }
    }
}
5.5.3.3. Status

MQTT connector supports the ONLINE, OFFLINE, REGISTERED and DEACTIVATED statuses. The following diagram shows how the MQTT connector sets interfaces' status.

Status state machine in MQTT connector

Interactive

5.5.3.4. Examples
5.5.3.4.1. Register a device with an MQTT interface

For more information on device creation, please see Register a device section.

Request:

POST /api/v1/deviceMgt/devices

{
    "id": "urn:lo:nsid:mqtt:mydevice_001",
    "tags": ["Lyon", "Test"],
    "name": "mySensor002",
    "description": "moisture sensor",
    "properties" : {
        "manufacturer": "Orange",
        "model": "MoistureSensorV3"
    },
    "interfaces": [
        {
            "connector": "mqtt",
            "enabled": true,
            "definition": {
                "clientId" : "mydevice_001"
            }
        }
    ],
    "group": {
        "id": "sWyaL2",
        "path": "/france/lyon"
    }
}

Response:

200 OK
{
    "id": "urn:lo:nsid:mqtt:mydevice_001",
    "name": "mySensor002",
    "description": "moisture sensor",
    "tags": [
        "Test",
        "Lyon"
    ],
    "properties": {
        "manufacturer": "Orange",
        "model": "MoistureSensorV3"
    },
    "group": {
        "id": "sWyaL2",
        "path": "/france/lyon"
    },
    "interfaces": [
        {
            "connector": "mqtt",
            "nodeId": "mydevice_001",
            "enabled": true,
            "status": "REGISTERED",
            "definition": {
                "clientId" : "mydevice_001"
            }
        }
    ],
    "defaultDataStreamId": "urn:lo:nsid:mqtt:mydevice_001",
    "created": "2018-03-06T11:30:42.777Z",
    "updated": "2018-03-06T11:30:42.819Z"
}

5.5.4. External connector

When you will connect devices that can not use a native connectivity in Live Objects (MQTT, LoRa®, SMS, COAP/LWM2M), you can use this API with the MQTT protocol and the external connector interface to connect and manage your devices. The protocol adapters (MQTT ⇐⇒ proprietary protocol) must be developed and maintained by the client.

The external connector mode purpose is to :

  • publish data and devices status

  • manage devices commands : subscribe to command requests and publish command responses

Typically, use this mode when you want to connect your back-end service (where your devices are connected to) to Live Objects.

"Connector" mode usage

Interactive

5.5.4.1. Definition

nodeId

the external connector’s id of the device. This is the shared id with Live Objects that will be used in all communication regarding this device.

encoding

Optional. name of the decoder that will be used to decode data received from this interface. It will override 'metadata.encoding' value from this device’s data messages. The decoder must be registered first (Cf. "Decoding service" section).

{
    "nodeId" : "myDevice_101",
    "encoding" : "myEncoding_v1"
}
5.5.4.2. Register a device with external connector interface

Before registering a device with an external connector interface, you must register a device. For more explanation on device creation, please see Register a device section.

Request:

POST /api/v1/deviceMgt/devices

{
  "id": "urn:lo:nsid:external:measures",
  "name": "sensor #12",
  "description": "MyDeviceMaker sensor #12",
  "defaultDataStreamId": "urn:lo:nsid:external:measures",
  "tags": [
    "demo",
    "sensor"
  ],
  "properties": {
    "manufacturer": "MyDeviceMaker, Inc.",
    "hwVersion": "2.0.1.7-us_64"
  },
  "interfaces": [
    {
      "connector": "x-connector",
      "enabled": true,
      "definition" : {
        "nodeId" : "myDevice1234"
      }
    }
  ]
}

Response:

{
  "id": "urn:lo:nsid:external:measures",
  "name": "sensor #12",
  "description": "MyDeviceMaker sensor #12",
  "tags": [
    "sensor",
    "demo"
  ],
  "properties": {
    "manufacturer": "MyDeviceMaker, Inc.",
    "hwVersion": "2.0.1.7-us_64"
  },
  "group": {
    "id": "root",
    "path": "/"
  },
  "interfaces": [
    {
      "connector": "x-connector",
      "nodeId": "myDevice1234",
      "enabled": true,
      "status": "REGISTERED",
      "definition": {
        "nodeId": "myDevice1234"
      },
      "capabilities": {
        "configuration": {
          "available": false
        },
        "command": {
          "available": false
        },
        "resource": {
          "available": false
        }
      },
      "created": "2020-02-06T09:31:44.461Z"
    }
  ],
  "defaultDataStreamId": "urn:lo:nsid:external:measures",
  "created": "2020-02-06T09:31:44.389Z",
  "updated": "2020-02-06T09:31:44.479Z",
  "activityState": "NOT_MONITORED"
}
When you register your device with an external connector interface, you must set a nodeId field in the definition section. The nodeId must be a string between 1 and 128 characters long, containing no spaces or special characters except :, - or _ . The nodeId must be unique.

When connected through this mode, this is the x-connector interface of the device which is used.

5.5.4.3. Auto-register

By default, the auto-provisioned deviceId for nodeId will be:

urn:lo:nsid:x-connector:{nodeId}

5.5.4.4. Status

The device behind the external connector interface supports only the REGISTRED, ONLINE and OFFLINE statuses. To learn more about how the device publish it’s statuses, see NodeStatus publication.

To learn more about how your extrenal connector work, see "External connector" mode section.

6. MQTT protocol

Live Objects supports the MQTT protocol to enable bi-directional (publish/subscribe) communications between devices or applications and the platform.

MQTT must be used with encryption (TLS layer). It is possible to use MQTT without encryption in "device" mode but we strongly recommend a secured connection. MQTT can be used with or without encryption (TLS layer).

Live Objects also supports MQTT over secure WebSocket.

The Live Objects MQTT interface offers multiples "modes":

  • mode "device": dedicated only to device connection use-cases, based on simple JSON messages,

  • mode "connector": dedicated to application that will act as cloud gateway and transfer device status and data from devices toward Live Objects

  • mode "application": useful for your business application to retreive data or event from Live Objects.

6.1. MQTT protocol support

MQTT protocol level supported is 3.1.1 (cf. MQTT Protocol Specification 3.1.1)

Live Objects acts as a standard MQTT message broker with some limitations:

  • the "will" functionality is not implemented, all "willXXX" flags and headers are not taken into account,

  • the "retain" functionality is not implemented,

  • the "duplicate" flag is not used,

  • the "clean session" flag is not used, the server always starts a new session.

Although Live Objects supports all control packets, QoS levels beyond the exchanges are not all fully guaranteed.

QoS definition guaranteed limitation

0

at most once delivery

yes

no

1

at least once delivery

yes

"duplicate" flag is not used,

2

exactly once delivery

no

same as QoS1


Live Objects has several application behaviors depending on the connection mode (user name) described in the following section. Currently Live objects supports 3 connection modes:

  • "device" mode used to communicate with a native MQTT device.

  • "external connector" mode is an API that allows communication with devices using other protocols not supported by Live Objects. To communicate with Live Objects, these devices are connected with a backend itself connected in "external connector" mode that can translate requests and responses (from / to) MQTT.

  • "application" mode with this mode, Live Objects provides an application mode to allow business applications to use the MQTT API.

6.1.1. Access topics restrictions

The first packet exchanged must be a MQTT CONNECT packet, sent from the client to the MQTT endpoint.

This packet must contain:

  • clientId: usage depends on the "mode", usually the deviceId in "device" mode

  • username: used to select a mode and encoding: (case sensitive)

  • password: an API Key with the mandatory roles depending of the connection mode

  • willRetain, willQoS, willFlag, willTopic, willMessage: ! Not taken into account !,

On reception, Live Objects validates the API key provided.

  • If the API key is valid, then Live Objects returns a MQTT CONNACK message with return code 0x00 Connection Accepted.

  • If the API key is not valid, then Live Objects returns a MQTT CONNACK message with return code 0x04 Connection Refused: bad username or password, and closes the TCP connection.

6.1.2. MQTT Ping Req/Res

Live Objects answers to MQTT PINGREQ packets with MQTT PINGRES packets: this is a way for the MQTT client to avoid connection timeouts.

6.1.3. MQTT Subscribe

Once connected, the client can at any time subscribe and unsubscribe to/from topics.

Live Objects answers with a MQTT SUBACK packet only once all subscriptions could be resolved:

MQTT specification enforce that a MQTT SUBACK is returned even if actual subscription is impossible / forbidden. In Protocol 3.1 the MQTT client cannot be informed that it subscribed to an non existing Topic. In Protocol 3.1.1 the MQTT client will receive MQTT SUBACK with corresponding QoS of 0x80 (Failure).

Live Objects answers to MQTT UNSUBSCRIBE packet with a MQTT UNSUBACK packet only once existing subscriptions have been properly closed.

6.1.4. MQTT Disconnect

Live Objects closes the MQTT / TCP connection when receiving a MQTT DISCONNECT message.

6.1.5. TCP Disconnect

When the TCP connection closes (by client or broker), the broker will close the currently active subscriptions, etc.

6.2. Endpoints

Type Modes Endpoint Description

MQTT

device

mqtt://mqtt.liveobjects.orange-business.com:1883

Unsecure plain MQTT connection. Not recommended.

MQTTS

mqtts://mqtt.liveobjects.orange-business.com:8883

Secure MQTTS connection. Recommended for device mode. Supports both server and client authentications.

Secure Websocket

wss://mqtt.liveobjects.orange-business.com:443/mqtt

Secure MQTTS connection over Websocket. Supports server authentication only.

MQTTS

application, connector

mqtts://liveobjects.orange-business.com:8883

Secure MQTTS connection. Recommended. Supports both server and client authentications.

Secure Websocket

wss://liveobjects.orange-business.com:443/mqtt

Secure MQTTS connection over Websocket. Supports server authentication only.


Live Objects MQTTS endpoint supports the following cipher suites:

  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 for TLS v1.2 only (recommended)

  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA

  • TLS_RSA_WITH_AES_128_GCM_SHA256 for TLS v1.2 only

  • TLS_RSA_WITH_AES_128_CBC_SHA

  • TLS_RSA_WITH_AES_256_CBC_SHA

TLS Server Name Indication (SNI) extension should be used for TLS connections. The SNI host_name field must match the target domain name. TLS connection is refused if host_name is invalid.

Mandatory: For TLS connections, MQTT devices MUST support:

  • At least TLS 1.2

  • Server Name Indication (SNI) extension

It is strongly recommended to use MQTTS for your production environment. Unsecured MQTT connections are not allowed for "Application" and "External connector" modes.

6.2.1. Legacy endpoints

Legacy endpoints liveobjects.orange-business.com are deprecated for device mode. TLS 1.0 and 1.1 on legacy endpoints is supported but deprecated. Legacy endpoints will be removed in the future

Type Modes Endpoint Description

MQTT

device

mqtt://liveobjects.orange-business.com:1883

Unsecure plain MQTT connection.

MQTTS

mqtts://liveobjects.orange-business.com:8883

Secure MQTTS connection. Supports both server and client authentications.

Websocket

wss://liveobjects.orange-business.com:443/mqtt

Unsecure plain MQTT connection over Websocket.

6.3. Secure your MQTT connection

6.3.1. Why use Secure MQTT protocol?

Using MQTT with TLS enabled provides privacy and data integrity between your devices/applications and Live Objects. It guarantees that your device/application is communicating with the authentic Live Objects platform, and it prevents a malicious third-party from eavesdropping or tampering. Using secure TLS communication is becoming a de facto standard when communicating over internet as more and more software / operating systems / Hardware refuse to communicate over non-encrypted protocols. Live Objects offers several levels of security that require adapted credentials according to the expected level of security.

6.3.2. MQTT security levels

3 security levels are available, for each one, the authentication is protected by TLS protocol and credentials, the client must have in its truststore and keystore the credentials below :

Authentication\ Credentials

Authentication level

clientId

API_KEY

Root CA certificate

Client certificate

MQTT

basic authentication

MQTTS server authentication

secured authentication

MQTTS server and client authentication

high secured authentication

6.3.3. MQTTS server authentication

A connection to the MQTT server secure endpoints requires that the MQTT clients maintain an up-to-date list of trusted root CA (Certificate Authority) certificates in order to seamlessly handle periodic server certificate updates.

6.3.3.1. Server Root CA certificates
domain name root certificate TLS supported version TLS mandatory options

mqtt.liveobjects.orange-business.com

DigiCert Global Root G2

TLS 1.2

Server Name Indication (SNI)

liveobjects.orange-business.com

DigiCert Global Root CA

TLS 1.0, 1.1, 1.2 (*)

(*)

(*) Support for TLS 1.0, 1.1 and connections without SNI extension will be removed in the future.

Your device must have in its truststore the root CA DigiCert Global Root G2. If your device use the Live Objects resource update (firmware) feature, it must also have in its trustore DigiCert Global Root CA.

Your application or external connector must have in its truststore the root CA DigiCert Global Root CA

  • Ensure that you can securely update your device or application software if security vulnerabilities are discovered.

  • Ensure that you have a way to update your root certificate list. Root CA are meant to be long-term certificates but Live Objects might have to change it.

  • Devices must be able to support at least two root CA certificates.

6.3.4. Go further with server and client authentication

Live Objects goes beyond server authentication and implements client authentication based on your own Certification Authority (CA). When enabled for a given API Key, Live Objects will:

  • make sure that only TLS with client authentication is made with this API key when used for MQTT connections

  • make sure that the client certificate has been signed by one of the CA certificates associated to the API key used by the device,

  • verify the identity of the device, by checking that client certificate’s Common Name (CN) matches the device id (in the MQTT client id). This last verification is done for MQTT “device” mode only. (i.e. not for MQTT “application” and “connector” mode)

Live Objects does not provide PKI services, but you can configure your Live Objects account to use your own PKI’s certificates. For the time being, a maximum limit of 10 certificates is set for a tenant.
6.3.4.1. Client certificat CA issuer requirements

Standard extensions

Basic constraints

A CA issuer certificate (which signed your client certificate) must include the basicConstraints value with the CA field set to TRUE. An end user certificate (device) must either set CA to FALSE or exclude the extension entirely.

You must check key usage extension of your CA issuer certificate, here are some common rules to consider :

Extension KeyUsage defined

In this case the KeyUsage extension must contains the permitted key usage with keyCertSign value. It can only be used to sign end user certificates and not further CAs. The end user certificates are used by the devices.

For example:

basicConstraints=CA:TRUE
keyUsage= keyCertSign <--

Extension KeyUsage not defined

Nothing to do. Your CA issuer can sign your devices certificates.

For example:

basicConstraints=CA:TRUE
without KeyUsage extension <--
Otherwise, in case where this rules are not respected, your CA certificate is rejected by Live Objects.
6.3.4.2. How to setup client authentication

The client authentication setup is done in 2 steps:

  • Make Live Objects aware of your Certification Authority (CA) by configuring the CA certificate which used to sign the devices certificates.

  • Check that your CA certificate meets standard requirements.

  • Associate that CA certificate with the API key used by your devices/external connector. This will force all communications to Live Objects using MQTT using that API key to be secured with a client certificate (or it will be rejected).

  • Generate a client certificate, signed with your CA certificate, with the MQTT Client ID as common name (CN) (for MQTT "device" mode only).

Client authentication is only available for MQTTS protocol. MQTT over secure websocket connection does not support client authentication.

1. Configure your Certification Authority’s intermediate certificate on Live Objects

Generate a key pair.

 openssl genrsa -out rootCA.key 2048

Use the key pair to generate your CA certificate.

 openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

Configure your certificate on Live Objects:

POST /api/v0/certificates/ca
 {
   "certificate": "your pem formatted certificate",
   "comment": "my awesome intermediate CA certificate"
 }

This call will return an id for your certificate.

Only provision the CA’s intermediate certificate that directly signed the device Certificate Signing Request (CSR).
 {
  "id": "your_certificate_id"
 }
To get a JSON compliant string of your pem certificate you can use the command line tool jq : cat rootCA.pem | jq -R --slurp

2. Associate this certificate with an Api Key

POST /api/v0/apiKeys/{your-api-key-id}
 {
   "clientCert": {
     "caCertIds": [
       "your-certificate-id1",
       "your-certificate-id2"
     ],
     "required": true
   }
 }
Once a certificate is associated with an Api Key and clientCert.required=true client authenticated MQTTS connection will be mandatory, otherwise the MQTT(s)/websocket connection will be closed with a Bad username or password error.

3. Generate a client certificate for a device with id *your-device-id*

Create a key pair for the device.

 openssl genrsa -out deviceCert.key 2048

Create a certificate signing request from your key pair

 openssl req -new -key deviceCert.key -out deviceCert.csr

Enter the information when prompted

 Country Name (2 letter code) []:
 State or Province Name (full name) []:
 Locality Name (for example, city) []:
 Organization Name (for example, company) []:
 Organizational Unit Name (for example, section) []:
 Common Name (e.g. server FQDN or YOUR name) []: <--------- ENTER YOUR DEVICE URN HERE
 Email Address []:

Generate the device certificate by signing the CSR with your Certification Authority intermediate key.

 openssl x509 -req -in deviceCert.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out deviceCert.pem -days 365 -sha256

4. Try it

Try your newly configured MQTTS with client configuration by sending a new data on the dev/data topic. We will be using the node mqtt.js client:

mqtt publish -h "mqtt.liveobjects.orange-business.com" --port 8883 -i your-device-id -q 0 -u json+device -C mqtts -t dev/data -m '{"s": "myStreamId", "v": {"temp": 12}}' --key your-cert-private-key --cert your-cert.pem --ca liveObjects.ca.cert.pem -P your-api-key
Once a certificate is associated with an Api Key and clientCert.required=true client authenticated MQTTS connection and MQTTS endpoint usage will be mandatory (see how to use MQTTS).

6.4. Debug MQTT/MQTTS connection

Usual error codes returned by MQTT connector when the client try to connect Live Objects over MQTT protocol :

Authentication

Username (depending on your MQTT mode)

API_KEY (password)

Root CA issuer certificate

API key CA certificate

Client certificate (CN=ClientID)

Connack return code

MQTT (basic authentication/TLS)

bad

bad

none

none

none

0x04 bad credentials

MQTT (basic authentication/TLS)

bad

compliant

none

none

none

0x04 bad credentials

MQTT (basic authentication/TLS)

compliant

bad

none

none

none

0x04 bad credentials

MQTT (basic authentication)

compliant

compliant

none

none

none

0x00 accepted

MQTTS server authentication (TLS)

compliant

compliant

Bad, expired or missing

none

none

0x05 not authorized

MQTTS server authentication (TLS)

compliant

compliant

compliant

none

none

0x00 accepted

MQTTS server and client authentication

compliant

compliant

compliant

compliant

none

0x05 not authorized

MQTTS server and client authentication

compliant

compliant

compliant

compliant

CN =/= client ID

0x05 not authorized

MQTTS server and client authentication

compliant

compliant

compliant

compliant

bad certificate chain

0x05 not authorized

MQTTS server and client authentication

compliant

compliant

compliant

compliant

compliant

0x00 accepted

6.5. "Device" mode

In the "Device" mode, a single MQTT connection is associated with a specific device, and JSON messages can be exchanged to support various Device Management and Data features:

  • notifying of the device connectivity status,

  • notifying of the current device configuration and receiving configuration updates,

  • notifying of the list of current device "resources" (i.e. binary contents) versions, and receiving resource update requests,

  • receiving commands and responding to them,

  • receiving configuration update and responding to it,

  • sending data messages that will be stored.

Device and data management features

landing

6.5.1. Connection

When initiating the MQTT connection, to select the "Device" mode you must use the following credentials:

  • clientId: your device unique identifier (cf. Device Identifier (URN)). It must be between 1 and 128 characters long, containing no spaces or special characters except :, - or _

  • username: json+device (case sensitive)

  • password: a valid API key value with DEVICE_ACCESS role

To find more information regarding Live Objects MQTT endpoints, please refer to: MQTT endpoints

We strongly recommend to use a secured connection (MQTTS port 8883).

As soon as the MQTT connection has been accepted by Live Objects, your device will appear as "ONLINE" in Live Objects, with various information regarding the MQTT connection.

Once you close the connection (or if the connection timeouts), your device will appear as "OFFLINE" in Live Objects.

6.5.2. MQTT client identity (URN)

The "clientId" value is used as MQTT client Id must be a valid Live Objects URN and conform to the following format:

urn:lo:nsid:{namespace}:{id}

Where:

  • namespace: your device interface identifier "namespace", used to avoid conflicts between various families of identifier (ex: device model, identifier class "imei", msisdn", "mac", etc.).

  • id: your MQTT clientId (ex: IMEI, serial number, MAC address, etc.)

"namespace" and "id" must only contain alphanumeric characters (a-z, A-Z, 0-9) or : - _ | + and must avoid # / !.*

Examples:

urn:lo:nsid:tempSensor:17872800001W
urn:lo:nsid:gtw_M50:7891001

6.5.3. Provisioning

By default, any device with a valid API Key will be able to connect to Live Objects using MQTT protocol.

You can explicitly define the MQTT capability for a device (see 'Device management - Interfaces' in Swagger documentation).

A device with an interface provisioned as "connector:"mqtt" and "enabled":false will not be able to connect to Live Objects through MQTT protocol.

6.5.4. Summary

Authorized MQTT actions for a device:

Direction

Topic

Description

Data message publication

publish to

dev/data

to publish a JSON data message

publish to

dev/v1/data/binary

to publish a binary data message and use a decoder associated to the device’s interface

publish to

dev/v1/data/binary/{encoding}

to publish a binary data message and use a decoder directly with the topic’s name

Command management

subscribe to

dev/cmd

to receive commands and announce remote command compatibility

publish to

dev/cmd/res

to return command responses

Configuration management

publish to

dev/cfg

to notify the current configuration or respond to a config update request

subscribe to

dev/cfg/upd

to receive configuration update requests and announce remote configuration update compatibility

Resource management

publish to

dev/rsc

to notify the current resource versions

subscribe to

dev/rsc/upd

to receive resource update requests and announce remote resource update compatibility

publish to

dev/rsc/upd/res

to respond to resource update requests

publish to

dev/rsc/upd/err

to notify resource update error

An AuditLog message will be sent if the device uses an unauthorized topic.

6.5.5. Data message publication

6.5.5.1. JSON data publication

Data published by devices through MQTT will be processed by the Data enrichment logic.

To publish JSON data into Live Objects, your device must publish on the MQTT topic dev/data the following messages:

{
    "streamId": "<<StreamId>>",
    "timestamp": "<<timestamp>>",
    "model": "<<model>>",
    "value": {
       "<<key>>":"<<value>>"      // a free JSON object
    },
    "location": {
       "latitude":<<>>,
       "longitude":<<>>,
       "altitude":<<>>,
       "accuracy":<<>>,
       "provider":<<>>
    },
    "tags": [<<tag1>>,<<tag2>>,...]
}

Message fields:

  • streamId : identifier of the timeseries this message belongs to,

  • timestamp : (optional) data/time associated with the message, is ISO 8601 format,

  • model : a string identifying the schema used for the "value" part of the message, to avoid conflict at data indexing,

  • value : a free JSON object describing the collected information,

  • tags : list of strings associated to the message used to carry extra-information,

  • latitude, longitude : details of the geo location associated with the message (in degrees),

  • altitude : height from sea level (in meters),

  • accuracy : the value depends on the combinaison of the tools provided the geo location tools (provider),

  • provider : GPS, cellular or custom

Please read this chapter to have the complete dataMessage description.

Example:

{
    "streamId": "mydeviceTemp1234",
    "timestamp": "2020-10-13T12:15:02Z",
    "model": "tempV2",
    "value": {
        "temp": 12.75,
        "humidity": 62.1,
        "doorOpen": true
    },
    "location": {
        "lat": 48.86667,
        "lon": 2.33333,
        "alt": 35.2,
        "accuracy": 12.3,
        "provider": "GPS"
    },
    "tags": [ "CityNYC", "Prototype" ]
}
6.5.5.2. Binary/hexa data publication

There are two different ways to publish binary data in Live Objects:

Topic Description

dev/v1/data/binary

Useful if you pre-provisioned your device using http API or the web portal. You can specify the "encoding" when the interface is created in the device inventory and use the decoding service. (1)

dev/v1/data/binary/{encoding}

This topic allows to specify directly the "encoding" that is used to match with a decoder name provisioned in Live Objects. With this topic, you don’t have to declare the "encoding" in the device inventory.

In both ways, the "encoding" value must match with the "name" of the decoder you want to use to decode the payload.

(1) The workflow if you prefer to declare the encoding in the device inventory is:

  • Create or update the device’s interface in the device inventory using http API or the web portal. See more information here.

  • Publish to the topic dev/v1/data/binary

In both cases, when pushing binary data, a dataMessage will be generated with the following values:

  • streamId: device urn

  • timestamp: timestamp of MQTT publication

  • value.payload: binary content of MQTT publication as a string in hexBinary www.datypic.com/sc/xsd/t-xsd_hexBinary.html

  • model: if a model is set in the decoder then it will be added. if not, this field is empty

When you publish binary data into Live Objects, only binary or javascript encoders (public or private) can be invoked. The csv decoder would not work in this case.

Please refer to the decoding service section for decoders management.

Examples:

Using the topic dev/v1/data/binary/{encoding}

  • Considering the following binary decoder already provisioned in Live Objects:

{
    "encoding": "my_encoding_v0",
    "format": "float sent_value;",
    "enabled": true,
    "model":"my_encoding_model_v0"
}
  • Sending a MQTT message with following bytes 0x41200000 as a payload on topic dev/v1/data/binary/my_encoding_v0, it will generate and store the following message:

{
    "timestamp" : "2020-10-31T16:15:21.288Z,"
    "streamId" : "urn:lo:nsid:mqtt:123456,"
    "value": {
        "payload": "41200000",
        "sent_value": 10.0
    },
    "model": "my_encoding_model_v0"
}

Using the topic dev/v1/data/binary

  • Declaration of the encoding in the device’s interface using http API: PATCH /api/v1/deviceMgt/devices/{deviceId}/interfaces/{interfaceId}

{
  "connector": "mqtt",
  "nodeId": "123456",
  "enabled": true,
  "status": "ONLINE",
  "definition": {
    "encoding": "my_encoding_v0",        // the name of the decoder that will be used to decode the payload
    "clientId": "123456"
  }
}

Considering the same decoder than in the previous example.

  • Sending a MQTT message with following bytes 0x41200000 as a payload on topic dev/v1/data/binary, it will generate and store the following message:

{
    "timestamp" : "2020-10-31T16:15:21.288Z,"
    "streamId" : "urn:lo:nsid:mqtt:123456,"
    "value": {
        "payload": "41200000",
        "sent_value": 10.0
    },
    "model": "my_encoding_model_v0"
}

6.5.6. Configuration

6.5.6.1. Current Configuration

To notify Live Objects of its current configuration, your device must publish a message to the MQTT topic dev/cfg with the following JSON structure:

{
   "cfg": {
      "<<param1Key>>": {
         "t": "<<param1Type>>",
         "v": <<param1Value>>
      },
      ...
   }
}

Message fields:

  • param{X}Key: the identifier for the device configuration parameters,

  • param{X}Type : indicates the config parameter type between

    • "i32": the value must be an integer from -2,147,483,647 to 2,147,483,647,

    • "u32": the value must a positive integer from 0 to 4,294,967,296,

    • "str": the value is a UTF-8 string,

    • "bin": the value is a base64 encoded binary content,

    • "f64": the value is float (64 bits) value,

  • param{X}Value : the config parameter value.

Example:

{
   "cfg": {
      "log_level": {
         "t": "str",
         "v": "DEBUG"
      },
      "secret_key": {
         "t": "bin",
         "v": "Nzg3ODY4Ng=="
      },
      "conn_freq": {
         "t": "i32",
         "v": 80000
      }
   }
}
6.5.6.2. Update Configuration

When your device is ready to receive configuration updates, it can subscribe to the MQTT topic dev/cfg/upd from where it will receive messages of the following format:

{
   "cfg": {
      "<<param1Key>>": {
         "t": "<<param1Type>>",
         "v": <<param1Value>>
      },
      ...
   },
   "cid": <<correlationId>>
}

Message fields:

  • param{X}Key : The identifier of a device configuration parameter that must be updated,

  • param{X}Type, param{X}Value : the new type and value to apply to the parameter,

  • correlationId : an identifier that your device must set when publishing your new configuration, so that Live Objects updates the status of your configuration parameters.

Example:

{
   "cfg": {
      "logLevel": {
         "t": "bin",
         "v": "DEBUG"
      },
      "connPeriod": {
         "t": "i32",
         "v": 80000
      }
   },
   "cid": 907237823
}
6.5.6.3. Response publication

Once your device has processed a configuration update request, it must return a response to Live Objects by publishing on topic dev/cfg the current value for the parameters that were updated:

{
   "cfg": {
      "<<param1Key>>": {
         "t": "<<param1Type>>",
         "v": <<param1Value>>,
      },
      ...
   },
   "cid": <<correlationId>>
}

Message fields:

  • config : the new configuration of your device (complete or at least all parameters that were in the configuration update request),

  • correlationId : the correlationId of the configuration update request.

Example:

{
   "cfg": {
      "logLevel": {
         "t": "bin",
         "v": "DEBUG"
      },
      "connPeriod": {
         "t": "i32",
         "v": 80000
      }
   },
   "cid": 907237823
}

If the new value for a parameter is the one that was requested in the configuration update request, the parameter will be considered as successfully updated by Live Objects.

If the new value for a parameter is not the one request, the parameter update will be considered as "failed" by Live Objects.

6.5.7. Commands

6.5.7.1. Retreive the command request

When your device is ready to receive commands, it can subscribe to the MQTT topic dev/cmd from where it can receive the following messages:

{
   "req":  "<<request>>",
   "arg": {
      "<<arg1>>": <<arg1Value>>,
      "<<arg2>>": <<arg2Value>>,
      ...
   },
   "cid":  <<correlationId>>
}

Message fields:

  • request : string identifying the method called on the device,

  • arg{X}, arg{X}Value : name and value (any valid JSON value) of an argument passed to the request call,

  • correlationId : an identifier that must be returned in the command response to help Live Objects match the response and request.

Example:

{
   "req":  "buzz",
   "arg": {
      "durationSec": 100,
      "freqHz":     800.0
   },
   "cid": 12238987
}
6.5.7.2. Response publication

To respond to a command, your device must publish the response to the MQTT topic dev/cmd/res with a message of the following format:

{
   "res": {
      "<<res1>>": "<<res1Value>>",
      "<<res2>>": "<<res2Value>>",
      ...
   },
   "cid":  <<correlationId>>
}

Message fields:

  • res{X}, res{X}Value : optional information returned by the command execution,

  • correlationId : a copy of the command correlationId value.

Example #1:

{
   "res": {
      "done": true
   },
   "cid": 12238987
}

Example #2:

{
   "res": {
      "error": "unknown method 'buzz'"
   },
   "cid": 12238987
}

Any response of the device will set the command state to PROCESSED and the optional information will be available in the command result.

6.5.8. Resources

6.5.8.1. Current Resources publication

Once connected, your device can announce the currently deployed versions of its resources by publishing a message on MQTT topic dev/rsc with the following format:

{
   "rsc": {
      "<<resource1Id>>": {
         "v": "<<resource1Version>>",
         "m": <<resource1Metadata>>
      },
      "<<resource2Id>>": {
         "v": "<<resource2Version>>",
         "m": <<resource2Metadata>>
      },
      ...
   }
}

Message fields:

  • resource{X}Id : resource identifier,

  • resource{X}Version : currently deployed version of this resource,

  • resource{X}Metadata : (JSON object) (optional) metadata associated with this resource, useful to resource update.

Example:

{
   "rsc": {
      "X11_firmware": {
         "v": "1.2",
         "m": {
            "size": <<firmware size in mbytes>>,
            "md5": "<<firmware sign>>",
         }
      },
      "X11_modem_driver": {
         "v": "4.0.M2"
      }
   }
}
6.5.8.2. Resources update

When your device is ready to receive resource update request, it just needs to subscribe to MQTT topic dev/rsc/upd. Then, the device will receive the request as a message in the following JSON format:

{
   "id": "<<resourceId>>",
   "old": "<<resourceCurrentVersion>>",
   "new": "<<resourceNewVersion>>",
   "m": {
      "size": <<firmware size in mbytes>>,
      "md5": "<<firmware sign>>",
   },
   "cid": "<<correlationId>>"
}

Message fields:

  • resourceId : identifier of resource to update,

  • resourceCurrentVersion : current resource version,

  • resourceNewVersion : new resource version, to download an apply,

  • correlationId : an identifier that must be returned in the resource update response to help Live Objects match the response and request.

Example:

{
   "id": "X11_firmware",
   "old": "1.1",
   "new": "1.2",
   "m": {
      "uri": "http://.../firmware/1.2.bin",
      "md5": "098f6bcd4621d373cade4e832627b4f6"
   },
   "cid": 3378454
}
6.5.8.3. Response publication

Once your device receives a "Resource update request", it needs to respond to indicate if it accepts or not the new resource version, by publishing a message on topic dev/rsc/upd/res with the following JSON format:

{
   "res": "<<responseStatus>>",
   "cid": "<<correlationId>>"
}

Message fields:

  • responseStatus : indicates the response status to the resource update request:

    • "OK" : the update is accepted and will start,

    • "UNKNOWN_RESOURCE" : the update is refused, because the resource (identifier) is unsupported by the device,

    • "WRONG_SOURCE_VERSION" : the device is no longer in the "current" (old) resource version specified in the resource update request,

    • "WRONG_TARGET_VERSION" : the device doesn’t support the "target" (new) resource version specified in the resource update request,

    • "INVALID_RESOURCE" : the requested new resource version has incorrect version format or metadata,

    • "NOT_AUTHORIZED" : the device refuses to update the targeted resource (ex: bad timing, "read-only" resource, etc.),

    • "INTERNAL_ERROR" : an error occurred on the device, preventing for the requested resource update,

  • correlationId : copy of the correlationId field from the resource update request.

Example #1:

{
   "res": "OK",
   "cid": 3378454
}

Example #2:

{
   "res": "UNKNOWN_RESOURCE",
   "cid": 778794
}
6.5.8.4. Response error

Device can report a custom resource update error by publishing a message on MQTT topic dev/rsc/upd/err with the following format:

{
   "errorCode":"ERROR_CODE",
   "errorDetails":"error details"
}

Message fields:

  • errorCode : (optional) device error code,

  • errorDetails : device error details

This fields are limited to 256 characters. Characters outside of this limit will be ignored.

Example:

{
   "errorCode":"DEV123.Z_FIRMW_CRC",
   "errorDetails":"error while loading firmware, bad CRC"
}

6.6. "External connector" mode

6.6.1. Connection

When initiating the MQTT connection, to select the "connector" mode you must use the following credentials:

  • clientId: any string between 1 and 128 characters long, containing no spaces or special characters except :, - or _ . The MQTT protocol indicates it must be unique per connection, but Live Objects does not enforce it.

  • username: connector (case sensitive)

  • password: a valid API Key with CONNECTOR_ACCESS role

To find more information regarding Live Objects MQTT endpoints, please refer to: MQTT endpoints

You must use a secured connection (MQTTS port 8883). The MQTT non-secured connection is not supported for "external connector" mode.

6.6.2. Summary

In "connector" mode, you can manage following device actions:

  • NodeStatus: publish in Live Objects a NodeStatus to set the ONLINE/OFFLINE status of the device (i.e. the node) and its capabilities

  • DataMessage: publish in Live Objects a DataMessage sent by the device

  • Command: subscribe to command requests and publish command responses

  • Configuration: handle configuration request or report modifications of a configuration of a device

  • Resource: manage resource update request or report current resource of a device behind the external connector

Direction Topic Description

NodeStatus publication

Publish

connector/v1/nodes/{nodeId}/status

To publish a NodeStatus for a device

Data message publication

Publish

connector/v1/nodes/{nodeId}/data

To publish a device DataMessage (telemetry event) to Live Objects

Commands

Subscribe

connector/v1/requests/command

To subscribe to command requests for devices. Commands can be manage through HTTP APIs.

Publish

connector/v1/responses/command

To publish a device command response

Configurations

Publish

connector/v1/current/configuration

To send a report of an initial configuration of a device to Live Objects

Subscribe

connector/v1/requests/configuration

To be notified (from Live Objects) of a configuration update for a device

Publish

connector/v1/responses/configuration

To respond/acknoledge to a device configuration request

Resources

Publish

connector/v1/current/resource

To send a report of resources current versions (firmware versions) of a device to Live Objects

Subscribe

connector/v1/requests/resource

To be notified (from Live Objects) of a resource version ugrade request

Publish

connector/v1/responses/resource

To respond/acknoledge to a resource version update request

6.6.3. NodeStatus publication

A NodeStatus publication allows to set the ONLINE/OFFLINE status of the device and its capacity to receive or not command requests.

The topic to publish is: connector/v1/nodes/{nodeId}/status

If the nodeId in the publication topic is unknown by Live Objects, a device with this NodeStatus information will be auto-provisioned in the Device inventory.

If the nodeId is already declared for a device in the Device inventory, then this NodeStatus information will update the corresponding device state in the Device inventory.

The link between a DeviceId and a NodeId is described in the Device and connectivity chapter.

The payload of this publication should follow :

NodeStatus publication
{
    "status": "ONLINE",
    "capabilities": {
        "command": {
            "available": true
        },
        "configuration": {
            "available": true
        },
        "resource": {
            "available": true
        }
    },
    "lastContact": "2019-05-20T16:01:47Z",
    "sessionSequenceId": 1,
    "eventSequenceId": 3
}

Only the 'status' field is mandatory.

Field Description

status

(Mandatory). Either 'ONLINE' or 'OFFLINE'.

capabilities.command

(Optional). Define if the device is able to receive commands. If true, you will be able to send commands to this device using the HTTP API.

capabilities.configuration

(Optional). Define if the device is able to receive configuration update. If true, you will be able to send new configurations to this device using the HTTP API.

capabilities.resource

(Optional). Define if the device is able to receive resource update. If true, you will be able to send new resource update to this device using the HTTP API.

lastContact

(Optional). Should follow ISO-8601 format. Set the lastContact information that will be updated in DataManager.

sessionSequenceId

(Optional). If present, the event will be taken into account only if no previous event had a higher sessionSequenceId.

eventSequenceId

(Optional). If present, the event will be taken into account only if no previous event had a higher sessionSequenceId or eventSequenceId.

As messages are asynchronously handled by Live Objects, sessionSequenceId and eventSequenceId mechanism allows to enforce message ordering (only the last status message will be taken into account). If this ordering is mandatory for your application, you should set them. For a unique MQTT session, sessionSequenceId should remain identical; and you can use epoch milliseconds from your application server as eventSequenceId.

If the publication succeeds, Live Objects will acknowledge the message according to the QoS level.

If the publication fails (for ex. because the JSON is badly formatted), Live Objects will nevertheless acknowledge the message according to the QoS level, and an AuditLog message will be sent with failure details.

6.6.4. Messages publication as a device

A DataMessage publication in the "connector" mode allows to send a DataMessage on behalf of a specific device.

The topic to publish is: connector/v1/nodes/{nodeId}/data

The payload of this publication should follow :

DataMessage publication
{
    "streamId": "urn:lo:nsid:detector_A8:12435355",
    "timestamp": "2019-05-20T16:01:47Z",
    "model": "data_v0",
    "value": {
        "temperature" : 14.6,
                "battery" : 53,
                "messageAlert":"low battery"
    },
    "location": {
        "lat": 48.86667,
        "lon": 2.33333,
        "alt": 35.2,
        "accuracy": 12.3,
        "provider": "GPS"
    },
    "tags": [ "production", "london" ]
}
Field Description

streamId

(Optional). The streamId where the data will be stored in; and retrieved using the HTTP store API. If not set, the default streamId set for this device in the Device inventory will be used. Should not contain any of the following character : ' " \ ; { } ( )

timestamp

(Optional). Should follow ISO-8601 format. If not set, current timestamp will be used.

model

(Optional). Can not contains ' ' (space) or '.' (dot) character. Model is needed to be able to use the search APIs on fields inside the value object.

value

(Optional). JSON compliant object. No inner field name should contains '.' (dot) character.

location

(Optional). If set, geo-query will be available through search APIs.

tags

(Optional) List of additional information used to tag the DataMessage

If the publication succeeds, Live Objects will acknowledge the message according to the QoS level.

If the publication fails (for ex. because the JSON is badly formatted), Live Objects will nevertheless acknowledge the message according to the QoS level, and an AuditLog message will be sent with anomaly details.

6.6.4.1. Encoded DataMessage publication

In order to use the decoding capability of Live Objects, a DataMessage must contains additional 'value.payload' and 'metadata.encoding' fields :

Encoded DataMessage publication
{
    "value": {
        "payload": "000003F5000000DD"
    },
    "metadata": {
        "encoding": "twointegers"
    }
}
Field Description

value.payload

(Mandatory). Payload to decode. In case of binary content, HexBinary String representation of the payload to decode.

metadata.encoding

(Mandatory). Encoded format name, that should match the 'encoding' name of the decoder that can process this message.

All other fields of DataMessage (streamId, timestamp, location, tags…​) can also optionally be set in the encoded DataMessage.

An alternative is to set the encoding property in the x-connector device’s interface definition through DeviceManagement APIs.

6.6.5. Commands

You can refer to commands description to have insights on the devices commands workflow. Using external connector mode, the basics are:

  • once connected in external connector mode, subscribe to command requests

  • create a command targeting a specific device using HTTP APIs or the web portal

  • when this device is connected (publishing a NodeStatus message with a command capability set to true), this command request is published into subscribed topic connector/v1/requests/command

  • optionally, publish the device command response

  • the command status is updated, and can be retrieved using HTTP APIs.

6.6.5.1. Retrieve the command request

Your external connector will receive all command requests targeting your devices.

This command requests are created through Live Objects HTTP APIs; please see dedicated section to know more about command requests.

The topic to subscribe is: connector/v1/requests/command

The received message in the subscribed topic has this model:

Command request message
{
    "id": "0f1253df-9b34-4e97-8e1e-457317107271",
    "nodeId": "myDevice",
    "value": {
        "req": "on",
        "args": {
            "level": 75
        }
    },
    "ackMode": "APPLICATIVE"
}
Field Description

id

(Mandatory). Unique id of the command request. The command response will use this id to correlate request and response.

nodeId

(Mandatory). Define the request’s targeted nodeId.

value

(Optional). The command request value that have been set when created through the HTTP API (any JSON Object).

ackMode

(Mandatory). The acknowledgement mode of this command (set when the command is created through the HTTP API). Either NONE, NETWORK or APPLICATIVE.

If ackMode is NETWORK or APPLICATIVE, a command response with the request’s id should be published as described command response section in order to update the command’s status. In this MQTT 'connector' mode, NETWORK and APPLICATIVE ackModes lead to the same behaviour.

6.6.5.2. Response publication

In order to reply to a command request, your external connector should publish to the topic: connector/v1/responses/command.

Command response message
{
    "id": "0f1253df-9b34-4e97-8e1e-457317107271",
    "nodeId": "myDevice",
    "response": {
        "status": "ok",
        "message": {
            "level": 75
        }
    }
}
Field Description

id

(Mandatory). id of the command request that triggered this response.

nodeId

(Mandatory). the nodeId which has generated the response (should be the same as the one in the request).

response

(Optional). This JSON Object will be stored as the command response when retrieved through he HTTP API.

With this response, the command’s status will change to PROCESSED. And if there is other command requests in queue for this device, the next one will be published.

If the publication succeeds, Live Objects will acknowledge the message according to the QoS level.

If the publication fails (for ex. because the JSON is badly formatted), Live Objects will nevertheless acknowledge the message according to the QoS level, and an AuditLog message will be sent with failure details.

6.6.6. Configurations

You can refer to configuration description to have insights on the devices configuration workflow.

Using external connector mode, the basics regarding this feature are:

  • connect to Live Objects MQTT in external connector mode, subscribe to configuration requests on the following topic connector/v1/requests/configuration

  • connect the device (publish a NodeStatus message with a configuration capability set to true),

  • set requested configuration targeting a specific device behind your external connector using HTTP APIs or the web portal

  • a configuration request will be received on the topic you suscribed above

  • when configuration is set on the device, your external connector publishes a device configuration response to connector/v1/responses/configuration

  • the configurations are updated, and can be retrieved using HTTP APIs: liveobjects.orange-business.com/api/v1/deviceMgt/devices/{deviceId}/config

Also, a device can change its configuration by itself. To report a configuration change, your external connector must publish in connector/v1/current/configuration

6.6.6.1. Retrieve the configuration request

Your external connector will receive all configuration requests targeting your devices.

These configuration requests are created through Live Objects HTTP APIs or web portal. Please see dedicated section to know more about configuration requests.

The topic to subscribe is: connector/v1/requests/configuration

The received message on the subscribed topic has this model:

Configuration request message
{
        "nodeId": "9ea64eb7-a5b4-4573-86e3-b6d949dc55a3",
        "targetVersion": 363745365,
        "parameters": {
                "my_param1": {
                        "type": "UINT32",
                        "value": 8035095625792325998
                },
                "my_param2": {
                        "type": "FLOAT",
                        "value": 0.8862329945028716
                },
                "my_param3": {
                        "type": "BINARY",
                        "value": "WldGbE16QXdtRmlPV1pt"
                },
                "my_param4": {
                        "type": "INT32",
                        "value": 1101263487
                },
                "my_param5": {
                        "type": "STRING",
                        "value": "my config as a string"
                }
        }
}
Field Description

nodeId

(Mandatory). Define the request’s targeted nodeId.

targetVersion

(Mandatory). The configuration request version for all provided parameters

parameters

(Mandatory). A JSON object where each field is a parameter name and each value a ParameterValue object. This format is the same that is used by the HTTP APIs. See the our swagger.

6.6.6.2. Response publication

In order to reply to a configuration request, your external connector must publish in the topic: connector/v1/responses/configuration.

configuration request and configuration response have the same format. To acknowledge a configuration request on a specific parameter, the response must contain the same target version and value.

Configuration response message
{
        "nodeId": "9ea64eb7-a5b4-4573-86e3-b6d949dc55a3",
        "targetVersion": 363745365,
        "parameters": {
                "my_param1": {
                        "type": "UINT32",
                        "value": 8035095625792325998
                },
                "my_param2": {
                        "type": "FLOAT",
                        "value": 0.8862329945028716
                }
        }
}

With this response, "my_param1" and "my_param2" are acknowledged. It can be checked on the portal or with HTTP APIs.

If the publication succeeds, Live Objects will acknowledge the message according to the QoS level.

If the publication fails (for ex. because the JSON is badly formatted), Live Objects will nevertheless acknowledge the message according to the QoS level, and an AuditLog message will be sent with failure details.

6.6.6.3. Publish the current device configuration in Live Objects

In addition to these two topics described in the previous chapter, Live Objects allows your external connector to announce current configuration of a device.

The topic to publish is: connector/v1/current/configuration

The message format is the same than before, except that there is no targetVersion.

Current configuration message
{
        "nodeId": "9ea64eb7-a5b4-4573-86e3-b6d949dc55a3",
        "parameters": {
                "my_param4": {
                        "type": "INT32",
                        "value": 123
                },
                "my_param5": {
                        "type": "FLOAT",
                        "value": 0.45562329946543
                }
        }
}

6.6.7. Resources

You can refer to resource description to have more information on the device resources management workflow.

Using external connector mode, the basics regarding this feature are:

  • Connect to Live Objects using MQTTS in external connector mode

  • Connect the device (publish a NodeStatus message with a resource capability set to true)

  • Send to Live Objects the current version of each device resource by publishing on connector/v1/current/resource

  • Subscribe to resources update requests with the following topic connector/v1/requests/resource

  • In order to update a resource for a given device, set its target version with HTTP APIs or the web portal

  • A resource update request will be received on the topic you suscribed above

  • Download the resource with the given resource url

  • Update your device with the resource (firmware)

  • (opt) Inform Live Objects of failure of the update process. Publish a device resource update response to connector/v1/responses/resource

  • When your resource is updated, send to Live Objects the new version of each device resource. publish on connector/v1/current/resource

  • The resource update informations can be retrieved using HTTP APIs: liveobjects.orange-business.com/api/v1/deviceMgt/devices/{deviceId}/resources/updates

6.6.7.1. Be notified of the resources update request

Your external connector will receive all resources update requests targeting your devices.

These resources update requests are created through Live Objects HTTP APIs or web portal. Please see dedicated section to know more about resource update.

The topic to subscribe is: connector/v1/requests/resource

The received message on the subscribed topic has this model:

resource update request message
{
        "nodeId": "CfnpFC6r",
        "resourceId": "my_resource",
        "updateCorrelationId": "5fc0db74e4332f0001aadf0c",
        "sourceVersion": "1.0",
        "targetVersion": "2.0",
        "delivery": {
                "type": "HTTP_DELIVERY",
                "uri": "https://liveobjects.orange-business.com:443/dl/r7n2b87cc6t8l6pst2t7avg1h5",
                "md5": "6dcdc9dcef09d8571994ac1b712b34c0",
                "size": 1024
        }
}
Field Description

nodeId

(Mandatory). Define the request’s targeted nodeId.

resourceId

(Mandatory). The resource id

updateCorrelationId

(Mandatory). The correlation id for this specific resource update

sourceVersion

(Mandatory). The current version of the resource

targetVersion

(Mandatory). The target version for the resource

delivery

Informations needed for resource download

delivery.type

should be HTTP_DELIVERY

delivery.uri

Download URI

delivery.md5

signature (md5) of the raw (non Base64-encoded) resource file

delivery.size

file size in bytes

6.6.7.2. Resource update report publication

In order to send a report to Live Objects on the resource update process, your external connector must publish on the topic: connector/v1/responses/resource.

The response is optional but is useful when an error occurs during the update process in the device side. If the update succeeded in the device side, your external connector must publish the current resources of the device. See the next chapter.
resource update response message
{
        "nodeId": "HA0lQz8R",
        "updateCorrelationId": "5fc10d40e4332f0001aadf39",
        "status": "FAILED",
        "error": {
                "code": "myErrorCode",
                "details": "myErrorDetails"
        }
}
Field Description

nodeId

(Mandatory). Define the request’s targeted nodeId

updateCorrelationId

(Mandatory). The correlation id for this specific resource update (provided by the resource update request)

status

(Mandatory). Only the status "FAILED" is accepted.

error.code

(Optional) in case of failure, error code (String).

error.details

(Optional) in case of failure, error details (String).

The update process status can be retrieved with HTTP API, using Device management - Resources APIs

6.6.7.3. Publish the current device resources' versions in Live Objects

Live Objects allows your external connector to report the current resources' versions of a device. This can be done at any time. When a resource update is done on the device side (firmware update for instance), the device must report this new version in order to update the resource version declared on the Live Object platform.

The topic to publish is: connector/v1/current/resource

Current resource message
{
  "nodeId": "CLcl0F4b",
  "resources": {
    "my_specific_resource": {
      "version": "1.0"
    },
    "my_firmware": {
      "version": "3.2"
    }
  }
}
Field Description

nodeId

(Mandatory). Define the request’s targeted nodeId.

resources

(Mandatory). map of resource names. The "version" field value must be a "string"

6.7. "Application" mode

In addition to the 2 modes available for devices, the MQTT protocol can also be used for data exchange between a business application and Live Objects. In this mode, the protocol is used by a third party application which requires a reliable link with Live Objects.

Due to the specific use of this mode, it is subject to restrictions and security limitations..

To learn more about "application mode" using MQTTS protocol see.

7. CoAP & LWM2M interface (Beta)

7.1. CoAP protocol

Constrained Application Protocol (CoAP) is an Internet Application Protocol for constrained devices (defined in RFC 7228) for M2M/Internet of Things. CoAP is a service layer protocol that is intended for use in resource-constrained internet devices, such as wireless low-power device. CoAP use HTTP for simplified integration on Rest architecture. CoAP can run on most devices that support UDP.

CoAP design is similar to HTTP principles but more effective on bandwidth and using UDP transport.

7.2. LWM2M protocol

OMA Lightweight M2M (LWM2M) is a protocol from the Open Mobile Alliance for M2M or IoT device management.

7.3. Principles

Live Objects exposes CoAP/LWM2M interface with these features:

  • Basic CoAP connection using DTLS (UDP) with PSK KEY identity

  • Data collect to upload a Live Objects JSON data message that will be stored

CoAP protocol is also used in LWM2M application protocol which is described in another section, see LWM2M protocol interface.

In order to provision a CoAP identity to connect your device, you will have to use the dedicated REST API as described in a following section.

The access to this interface is an option, as for now you need to contact our support team to get it enabled in your tenant.

7.4. Endpoints

For the LWM2M protocol, only secured CoAP binding is supported using DTLS Pre-Shared Key (PSK).

    coaps://lwm2m.liveobjects.orange-business.com:5684

7.5. Content

Currently only Live Objects JSON data message format is supported to be uploaded using the CoAP\LWM2M Interface.

The data decoding is not yet available on this interface.

7.6. CoAP\LWM2M device Provisioning

7.6.1. Using Live objects API

The DTLS authentication for CoAP\LWM2M adds new concepts not compatible with API key of Live Objects. So you have to provision this new type of credentials (see the dedicated swagger):

    POST /api/v0/vendors/lwm2m/identities
{
    "device": "URN",
    "ep": "the device's endpoint",
    "pubKeyOrIdentity": "pubKeyOrIdentity",
    "secretKey": "\"something base 64\"",
    "securityMode": "PSK",
    "tags": [
    "tag1",
    "tags2"
    ],
}

With the given details:

  • device : your device unique identifier (cf. Device Identifier (URN)),

  • ep : the device’s endpoint, the same value as the device URN,

  • pubKeyOrIdentity : the identity used for PSK identity,

  • secretKey : the PSK passwork associated to the identity, encoded in base64,

  • securityMode : must be set to PSK string value.

You can do these steps using the portal GUI, located in menu Devices > CoAP \ LWM2M

7.6.2. Using Live Objects portal

LWM2MProv.png

With the following sample values:

  • Endpoint, Identity and Park with value "urn:lwm2m:device4"

  • Security Mode with value "Pre-Shared Key"

  • Secret Key with a base64 value of the password

7.7. CoAP device simulation

7.7.1. Posting CoAP\LWM2M message

Once the identity provisioned, the CoAP device can send a valid Live Objects CoAP data message model.

The following sample will provide a simulator in Java:

    git clone https://github.com/eclipse/californium.tools
  • and run the following commands (Java JDK and Maven are required)

    cd californium.tools/cf-client
    mvn clean install
    cd ..\run

To test your device, execute the following steps using the credentials previously created:

  • Choose your own password for PSK key (for ex: “password”) then encode it in B64. (See here www.base64decode.org )

  • Create your CoAP device (if not yet) with Live Objects portal (LWM2M menu) and enter the previous key encoded in B64. Do not use the generate button for that

  • Run the CoAP DTLS client Californium with the following command line

java -jar cf-client-1.1.0-SNAPSHOT.jar -psk POST coaps://lwm2m.liveobjects.orange-business.com:5684/data "{\"streamId\": \"urn:lwm2m:device4!uplink\", \"model\": \"testmodel\", \"value\":{\"testproperty\": \"testvalue\" }}"
  • Then you will be prompted to give the PSK Identity (previously provisioned as pubKeyOrIdentity) and the Secrey Key (previously provisioned as secretKey) in ascii string, not encoded in B64 → “password” in our example

  • You should see the data published in the Data menu of your portal

In a more readable manner, the JSON Live Objects data message in this sample is:

{
    "streamId": "urn:lwm2m:device4!uplink",
    "model": "testmodel",
    "value":{
            "testproperty": "testvalue"
    }
}

7.7.2. Californium CoAP result view

COAPResult.png

7.8. Using LWM2M

7.8.1. LWM2M device parameters view

LWM2MDeviceInfo.png

JSON object model :

{
  "page": 0,
  "size": 20,
  "totalCount": 2,
  "data": [
    {
      "ep": "urn:lo:nsid:lwm2m:device1:2caf4e244430430e",
      "securityMode": "PSK",
      "pubKeyOrIdentity": "a1ebc03a72cf0671",
      "device": "urn:lo:nsid:lwm2m:device1",
      "creationTs": 1544019251440,
      "updateTs": 1544019251440
    },
    {
      "ep": "urn:lo:nsid:lwm2m:device2",
      "securityMode": "PSK",
      "pubKeyOrIdentity": "32202c4215c03f76",
      "device": "urn:lo:nsid:lwm2m:device2",
      "creationTs": 1544020350136,
      "updateTs": 1544020350136
    }
  ]
}

LWM2M Notify messages are converted to Live Objects JSON data message. The screenshot below shows

a data message from an observe action on an LWM2M resource named "/3" (which is the standardised Device definition):

7.8.2. LWM2M data message model

LWM2MIm6.png

Or as text:

    {
        "metadata": {
        "source": "urn:lwm2m:device4",
        "connector": "coap",
        "network": {
        "lwm2m": {
        "ep": "urn:lwm2m:device4"
            }
        }
    },
    "streamId": "urn:lwm2m:device4!uplink",
    "created": "2017-08-24T13:29:54.087Z",
    "location": null,
    "model": "urn:oma:lwm2m:oma:3",
    "id": "599ed4d2a1a7e86004e2a4b8",
    "value": {
        "Device": {
        "0": {
        "17": "RGVtbw==",
        "18": "MS4wLjE=",
        "19": "MS4wLjI=",
        "20": "Ag==",
        "21": "AAHsAA==",
        "Battery Level": 50,
        "Timezone": "Europe/Paris",
        "Firmware Version": "1.0.0",
        "Memory Free": 93674,
        "Current Time": "2017-08-24T13:29:51.000+0000",
        "UTC Offset": "+02",
        "Model Number": "Model 500",
        "Serial Number": "LT-500-000-0001",
        "Error Code": {
            "0": 0
            },
            "Manufacturer": "Leshan Demo Device",
            "Supported Binding and Modes": "U"
            }
        }
    },
        "timestamp": "2017-08-24T13:29:53.766Z",
        "tags": []
    }

Where:

  • the streamId and the model are generated from the observed resource

8. Device management

8.1. Device group

8.1.1. Principle

A group enables to bring devices together. Groups can be used to :

  • ease browsing and sorting on Live Objects web portal.

  • using inventory explorer, count and aggregate your devices fleet, select a sub set (group) of your devices fleet by criterias to manage it.

  • apply different forwarding rules on the data collected from the devices (Cf. "Notifications" section).

  • apply different event processing and alarming rules (Cf. "Alarming" chapter).

Groups behave mostly like directories in a filesystem (considering devices are files): a Group can include other groups and devices. For instance a device can only belong to one group at a time. There are however some exceptions to this analogy (see group deletion rules).

Each tenant has a default root group. A group, except root group, must have a parent group and can have subgroups. In the same tenant, the complete path of each group must be unique but several groups can have the same local identifier (pathNode). The complete path enables to have the tree view of your group.

Group object model:

JSON Params Description

id

group unique identifier

pathNode

Optional. local group id in path

path

complete group path

parentId

Optional. parent group identifier

description

Optional. detailed description of the group

created

creation date of the device

updated

last update date of the device

The group id is fixed, but the group path is calculated because he depends on both the pathNode and the location of the group in the tree. Moving a group in the tree logically leads to a modification of the group path.

Example:

{
    "id": "u1z1k8",
    "pathNode": "lyon",
    "path": "/france/lyon",
    "parentId": "P2112f",
    "description": "City of Lyon",
    "created": "2018-02-14T16:53:54.515Z",
    "updated": "2018-02-14T16:53:54.515Z"
}
Groups tree view

Interactive

8.1.2. Create a new group

8.1.2.1. Request

Endpoint:

POST /api/v1/deviceMgt/groups

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Body:

JSON Params Description

pathNode

group local identifier in path (unique for groups with the same parent)

parentId

Optional. reference to group parent (id). Root group by default.

description

Optional. detailed description of the group

Example:

POST /api/v1/deviceMgt/groups
{
    "pathNode":"lyon",
    "parentId":"P2112f",
    "description":"City of Lyon"
}
8.1.2.2. Response

HTTP Code:

201 CREATED

Body:

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

401

UNAUTHORIZED

Authentication failure.

403

GENERIC_ACTION_FORBIDDEN_ERROR

Request forbidden.

404

DM_GROUP_NOT_FOUND

Group not found

409

DM_GROUP_DUPLICATE

Conflict on group path

Example:

{
    "id": "u1z1k8",
    "pathNode": "lyon",
    "path": "/france/lyon",
    "parentId": "P2112f",
    "description": "City of Lyon",
    "created": "2018-02-14T16:53:54.515Z",
    "updated": "2018-02-14T16:53:54.515Z"
}

8.1.3. Update a group

The path change of a group does not change its content (Devices, Groups).

8.1.3.1. Request

Endpoint:

PUT /api/v1/deviceMgt/groups/<id>

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Body:

JSON Params Description

pathNode

Optional. group local id in path (unique for groups with the same parent)

parentId

Optional. reference to group parent (id). Root group by default

description

Optional. detailed description of the group

Example:

PUT /api/v1/deviceMgt/groups/u1z1k8
{
    "pathNode":"paris",
    "parentId":"P2112f",
    "description":"City of Paris"
}
8.1.3.2. Response

HTTP Code:

200 OK

Body:

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

401

UNAUTHORIZED

Authentication failure.

403

GENERIC_ACTION_FORBIDDEN_ERROR

Request forbidden.

404

DM_GROUP_NOT_FOUND

Group not found

Example:

{
    "id": "u1z1k8",
    "pathNode": "paris",
    "path": "/france/paris",
    "parentId": "P2112f",
    "description": "City of Paris",
    "created": "2018-02-14T16:53:54.515Z",
    "updated": "2018-02-15T10:31:26.667Z"
}

8.1.4. List groups

8.1.4.1. Request

Endpoint:

GET /api/v1/deviceMgt/groups

Query parameters:

Name Description

limit

Optional. maximum number of groups in response. 20 by default.

offset

Optional. the number of entries to skip in the results list. 0 by default.

parentId

Optional. filter list by group’s parent. When a parent is set, only direct children are returned (one level).

groupPath

Optional. filter list by group’s path. When a full path is set, only nodes matching exactly this path are returned. In order to return nodes matching a path and all descendants, you must end the groupPath with /* (ex. /spain/*). In order to return direct children nodes -only- of a path, the groupPath must end with /*/ (ex. /spain/*/).

List Groups Query samples:

QueryParams Returned nodes

?groupPath=/france

/france

?groupPath=/*

/france, /france/lyon,/france/paris, /italia

?groupPath=/france/*

/france, /france/lyon,/france/paris

?groupPath=/france/*/

/france/lyon,/france/paris

?parentId=root

/france, /italia

?parentId=P2112f&groupPath=/*

/france/lyon,/france/paris

?parentId=P2112f&groupPath=/france/*

/france/lyon,/france/paris

?parentId=root&groupPath=/france/*

no result

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json
X-Total-Count: <boolean>

For more info about X-Total-Count, see "API v1 paging" section.

Example:

GET /api/v1/deviceMgt/groups?limit=20&offset=0
8.1.4.2. Response

HTTP Code:

200 OK

Body:

Example:

[
    {
        "id": "root",
        "path": "/",
        "created": "2017-11-03T15:23:22.771Z",
        "updated": "2017-11-03T15:23:22.771Z"
    },
    {
        "id": "P2112f",
        "pathNode": "france",
        "path": "/france",
        "parentId": "root",
        "description": "",
        "created": "2018-02-14T16:47:37.318Z",
        "updated": "2018-02-14T16:47:37.318Z"
    },
    {
        "id": "u1z1k8",
        "pathNode": "paris",
        "path": "/france/paris",
        "parentId": "P2112f",
        "description": "City of Paris",
        "created": "2018-02-14T16:53:54.515Z",
        "updated": "2018-02-15T10:31:26.667Z"
    }
]

8.1.5. Get a group

8.1.5.1. Request

Endpoint:

GET /api/v1/deviceMgt/groups/<id>

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json

Example:

GET /api/v1/deviceMgt/groups/u1z1k8
8.1.5.2. Response

HTTP Code:

200 OK

Body:

Error case:

HTTP Code Error code message

404

DM_GROUP_NOT_FOUND

Group not found

Example:

{
    "id": "u1z1k8",
    "pathNode": "paris",
    "path": "/france/paris",
    "parentId": "P2112f",
    "description": "City of Paris",
    "created": "2018-02-14T16:53:54.515Z",
    "updated": "2018-02-15T10:31:26.667Z"
}

8.1.6. Delete a group

You can’t delete a group which has devices.

8.1.6.1. Request

Endpoint:

DELETE /api/v1/deviceMgt/groups/<id>

HTTP Headers:

X-API-Key: <your API key>
Accept: application/json

Example:

DELETE /api/v1/deviceMgt/groups/u1z1k8
8.1.6.2. Response

HTTP Code:

204 NO CONTENT

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

401

UNAUTHORIZED

Authentication failure.

403

DM_GROUP_UNDELETABLE

Group can’t be deleted: contains devices or sub-groups

404

DM_GROUP_NOT_FOUND

Group not found

8.2. Configuration

Currently, APIs allow to manage configuration only for MQTT connector.

8.2.1. Principle

A device can declare one or many parameters: a parameter is identified by a string "key" and can take a typed value (binary, int32, uint32, timestamp).

Live Objects can track the changes of the current value of a device parameters, and allow users to set different target values for those parameters. Live Objects will then try to update the parameters on the device once it’s connected and available.

Device configuration sync steps

Interactive

  • (before) :

    • device initiates MQTT connection with Live Objects,

    • device subscribes in MQTT to a private topic, where it will receive later the configuration update requests,

  • step 0 : device notifies Live Objects that it is connected and available for configuration updates on a specific topic,

  • step 1 : device notifies Live Objects of its current configuration,

  • step 2 : Live Objects compares the current and target configuration for this device. If they differ:

    • step 3 : Live Objects sends to the device, on the topic indicated at step 0, the list of parameters to update, with their target value,

    • step 4 : device handles the request, and tries to apply the change(s),

    • step 5 : device respond to the change request with the new configuration,

    • step 6 : Live Objects saves the new configuration. Parameters that have been successfully updated now have the status "OK" and the others the status "FAILED".

Device configuration sync states

Interactive

If your device is connected in Device mode, please refer to the MQTT device mode part for messages that your device can send or receive.

8.2.2. Get device configuration parameters

To retrieve the details of the configuration map of the device we can use the GET API.

8.2.2.1. Request

Endpoint:

GET /api/v1/deviceMgt/devices/<deviceId>/config/parameters

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Example:

GET /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/config/parameters
8.2.2.2. Response

HTTP Code:

200 OK

Body:

For each parameter, the following information is available :

{
  "{paramKey}": {
    "reported": {
        "type": {paramType},
        "value": {paramValue},
        "timestamp": {timestampsValue}
    },
    "requested": {
        "type": {paramType},
        "value": {paramValue},
        "timestamp": {timestampsValue}
    },
    "syncStatus": {paramStatus}
}

With:

paramKey

string uniquely identifying the device configuration parameter

paramType

indicates the config parameter type between: INT32, UINT32, BINARY, STRING or FLOAT

paramValue

value requested for the parameter

timestampsValue

update date of the parameter

paramStatus

parameter update status: NONE, PENDING, SENT, CANCELED, OK or FAILED

The section reported is present when the device has answered and corresponds to parameter configuration returned by the device, the paramStatus could be OK or FAILED.

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

404

DM_DEVICE_NOT_FOUND

Device not found

Example:

{
  "param1" : {
    "requested" : {
      "type" : "INT32",
      "value" : 1,
      "timestamp" : "2018-08-23T08:10:01.029Z"
    },
    "syncStatus" : "PENDING"
  },
  "param2" : {
    "requested" : {
      "type" : "UINT32",
      "value" : 4321,
      "timestamp" : "2018-08-01T14:39:16.216Z"
    },
    "syncStatus" : "PENDING"
  },
  "param3" : {
    "reported" : {
      "type" : "FLOAT",
      "value" : 3.2,
      "timestamp" : "2018-04-26T08:16:33.681Z"
    },
    "requested" : {
      "type" : "FLOAT",
      "value" : 3.2,
      "timestamp" : "2019-06-17T12:52:20.930Z"
    },
    "syncStatus" : "OK"
  },
  "param4" : {
    "requested" : {
      "type" : "BINARY",
      "value" : 11001,
      "timestamp" : "2018-08-01T14:37:52.579Z"
    },
    "syncStatus" : "CANCELED"
  },
  "param5" : {
    "reported" : {
      "type" : "STRING",
      "value" : "my data",
      "timestamp" : "2018-03-29T08:48:20.810Z"
    },
    "requested" : {
      "type" : "STRING",
      "value" : "info",
      "timestamp" : "2018-03-29T08:48:20.813Z"
    },
    "syncStatus" : "FAILED"
  }
}

8.2.3. Set device configuration parameters

8.2.3.1. Request

Endpoint:

POST /api/v1/deviceMgt/devices/<deviceId>/config

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Body:

JSON Params Description

parameters

list of device configuration update

notifyTo

Optional. topic where configuration change/sync events must be published to

Each parameter to update must have the following structure:

"{paramKey}": {
    "type": {paramType},
    "value": {paramValue}
}

With:

paramKey

a string uniquely identifying the device configuration parameter. Should not start with $ character

paramType

indicates the config parameter type between

"INT32"

the value must be an integer from -2,147,483,648 to 2,147,483,647,

"UINT32"

the value must a positive integer from 0 to 4,294,967,295,

"BINARY"

the value is a base64 encoded binary content,

"STRING"

the value is a UTF-8 string,

"FLOAT"

the value is float (64 bits) value.

Example:

POST /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/config
{
    "parameters": {
        "MyParamINT32" : {
            "type" : "INT32",
            "value" : -333
        },
        "MyParamSTRING" : {
            "type" : "STRING",
            "value" : "My sentense"
        }
    },
    "notifyTo": "fifo/configUpdateFifo"
}
8.2.3.2. Response

HTTP Code:

200 OK

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

If the device does not exist, it will be auto-provisionned.

8.2.4. Get a description of the device configuration

8.2.4.1. Request

Endpoint:

GET /api/v1/deviceMgt/devices/<deviceId>/config

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Example:

GET /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/config
8.2.4.2. Response

HTTP Code:

200 OK

Body:

JSON Params Description

parameters

list of device configuration update

notifyTo

Optional. topic where configuration change/sync events must be published to

For each parameter, the following information is available :

{
  "parameters" : {
      "{paramKey}": {
          "reported": {
              "type": {paramType},
              "value": {paramValue},
              "timestamp": {timestampsValue}
          },
          "requested": {
              "type": {paramType},
              "value": {paramValue},
              "timestamp": {timestampsValue}
          },
          "syncStatus": {paramStatus}
      }
  }
  "notifyTo": ""
}

With:

paramKey

string uniquely identifying the device configuration parameter

paramType

indicates the config parameter type between: INT32, UINT32, BINARY, STRING or FLOAT,

paramValue

value requested for the parameter,

timestampsValue

update date of the parameter,

paramStatus

parameter update status; NONE, PENDING, SENT, OK or FAILED.

The section reported is present when the device has answered and corresponds to parameter configuration return by the device, the paramStatus could be OK or FAILED.

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

404

DM_DEVICE_NOT_FOUND

Device not found

Example:

{
    "parameters": {
        "MyParamFLOAT": {
            "requested": {
                "type": "FLOAT",
                "value": 1245,
                "timestamp": "2018-03-07T10:55:21Z"
            },
            "syncStatus": "PENDING"
        },
        "MyParamBINARY": {
            "requested": {
                "type": "BINARY",
                "value": "Nzg3ODY4Ng==",
                "timestamp": "2018-03-07T10:54:55.948Z"
            },
            "syncStatus": "SENT"
        },
        "MyParamINT32": {
            "reported": {
                "type": "INT32",
                "value": -333,
                "timestamp": "2018-03-07T10:53:21.934Z"
            },
            "requested": {
                "type": "INT32",
                "value": -333,
                "timestamp": "2018-03-07T10:53:21.937Z"
            },
            "syncStatus": "OK"
        }
    },
    "notifyTo": "fifo/configUpdateFifo"
}

8.2.5. Get state of a specific device configuration parameter

8.2.5.1. Request

Endpoint:

GET /api/v1/deviceMgt/devices/<deviceId>/config/parameters/<paramKey>

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Example:

GET /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/config/parameters/MyParamFLOAT
8.2.5.2. Response

HTTP Code:

200 OK

Body:

JSON Params Description

reported

Optional. reported configuration parameter value

requested

requested configuration parameter value

syncStatus

parameter update status; NONE, PENDING, SENT, CANCELED, OK or FAILED

Error case:

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

404

DM_DEVICE_CONFIG_PARAM_NOT_FOUND

Device configuration parameter not found

Example:

{
    "requested": {
        "type": "FLOAT",
        "value": 1245,
        "timestamp": "2018-03-07T10:55:21Z"
    },
    "syncStatus": "PENDING"
}

8.3. Commands

This section describe how to set up command requests before sending them to the devices.

The Concepts and API described in this chapter allows to manage commands for MQTT, LoRa®, SMS and external connector interfaces.

8.3.1. Principle

A command request is a downlink message that Live Objects sends to the device, with acknowledgement mechanism. Depending on the interface (protocol & connectivity) used, a command response can be sent by the device to Live Objects.

You can register commands targeting a specific device: as soon as an interface for this device is available for commands, Live Objects will send them one by one, waiting for an acknowledgment for each command before sending the next one.

There is a limitation of 10 queued commands for a specific device.

Live Objects keeps a record of every registered command with its status, and possible response after processing by device.

The command control mechanism consists of two sub-mechanisms :

  • an application sub-mechanism that manages the displayed command statuses for the buisness applications and apply command cancel if need.

  • an additional sub-mechanism that manages the command delivery status to the device using the connectors.

8.3.2. Command status

The commands can have the following states:

Status Description

PENDING

The command is recorded and waiting for processing

RETRYING

The command has encountered an error, and will be retried. (same behaviour as PENDING)

PROCESSING

The command is being processed by the dedicated interface (waiting for an acknowledge)

PROCESSED

The command has reached its final acknowledgement level (FINAL STATE)

ERROR

An error occurred during the processing of the command (FINAL STATE)

CANCELED

The command was canceled before reaching PROCESSED state (FINAL STATE)

EXPIRED

The command could not be processed within the time limit (expirationTimeoutInSecond) (FINAL STATE)

Here is a status diagram with possible transitions:

Device commands states

Interactive

8.3.3. Command status summary table

Table 1. Here is the list of possible command statuses provided by each connectivity

Command Status \ Connector

LoRa®

MQTT

SMS

External Connector

PENDING

PROCESSING

PROCESSED

EXPIRED

CANCELED

RETRYING

ERROR

8.3.4. Delivery status

During the PROCESSING state, the device manager exposes an additional information: the delivery status. The delivery status provides more detailed information on the processing step of the command, based on the acknowledgement information available, depending on the connectivity used.

Device commands delivery states

Interactive

8.3.5. Acknowledgement level

The acknowledgement level determines the transition from the PROCESSING state to the PROCESSED state of a command.

The device manager offers three different levels of acknowledgement:

  • NONE : The device manager only listens to the internal acknowledgement that notifies the sending of the command. The command is output from Live Objects. Equivalent to the delivery status SENT

  • NETWORK : The device manager waits for protocol acknowledgment. Equivalent to the delivery status DELIVERED

  • APPLICATIVE : The device manager waits for an applicative acknowledgement, with potentially a response. Equivalent to the delivery status REPLIED

For each connector, the acknowledgement level implies a specific delivery status as described in MQTT acknowledge/status, LoRa® acknowledge/status, SMS acknowledge/status, External connector acknowledge/status.

8.3.6. Expiration Timeout

In most cases, the device availability cannot be accurately predicted, due to connectivity reason for example. In some cases, we need the command to be executed in a near future or not at all.

Let’s return to the example of our connected lock: when we send an "unlock" command, we want that the command will be executed within the next two minutes, not in three hours due to a connectivity issues.

The command API proposes the expiration timeout (default: 7 days, max: 30 days). This is the maximal amount of time allowed to reach the status PROCESSING. If this value is exceeded, the status of the command goes to the status EXPIRED.

8.3.7. Acknowledgement Timeout

The command API proposes the acknowledgement timeout. This is the maximal amount of time allowed to reach the status PROCESSED when command is being processed (status PROCESSING). If this value is exceeded, the status of the command goes to the status ERROR with the error code ACK_TIMEOUT.

For each connector, the acknowledgement level implies a specific delivery status as described in MQTT ack timeout value, LoRa® ack timeout value, External connector ack timeout value.

A command with NONE acknowledgement cannot have acknowledgement timeout.
Do not hesitate to customize this value. A value adjusted to your needs allows for better error detections, as well as a better reactivity of the command process

8.3.8. Attempts number

For some reasons (network issues, or acknowledgement default), a command can reach the acknowledgement timeout. In this case, we may have to retry sending command. This is the purpose of the attempts field in the command policy.

If another attempt can be made, instead of ERROR, the command status is set to RETRYING, equivalent to the PENDING status, but showing that it’s not the first attempt. Then, the command is treated normally.

If all attempts have been used, the command status is set to ERROR.

The default value of attempts is 1, wich means there will be no retries. The maximum value is 5 (first attempt + 4 retries)
If the command status is RETRYING and the expiration timeout is reached, the new attempts is abort, and the command status is set to EXPIRED (same behavior as PENDING). It is advisable to define an expiration timeout upper than (acknowldegement timeout x (attempts - 1))

8.3.9. Command object model

We will detail the command object model of the device manager, as used in API v1.

All possible operations on this object are detailed in the swagger.

Here is an unrealistic example, using a blank interface :

{
    "id": "ae49129f-9ce4-4782-82c4c6a2",
    "targetDeviceId": "urn:lo:nsid:sensor:2327398",
    "request": {
        "connector": "...",
        "value": {
            [...]
        }
    },
    "response": {
      [...]
    },
    "status": "PROCESSED",
    "deliveryStatus": "REPLIED",
    "errorCode": "INVALID_COMMAND_REQUEST",
    "policy": {
        "expirationInSeconds": 120,
        "ackTimeoutInSeconds": 180,
        "ackMode": "APPLICATIVE",
        "attempts" : 1
    },
    "history": [
        {
            "timestamp": "2017-12-06T11:32:25.055Z",
            "status" : "PENDING"
        }, {
            "timestamp": "2017-12-06T11:38:22.481Z",
            "status": "PROCESSING",
            "deliveryStatus": "SENT",
            "errorCode": "INVALID_COMMAND_REQUEST",
            "nodeId": "2327398"
        }, {
            "timestamp": "2017-12-06T11:38:24.124Z",
            "status": "PROCESSED",
            "deliveryStatus": "REPLIED",
            "nodeId": "2327398",
        }
    ],
    "created": "2017-12-06T11:32:25.055Z",
    "updated": "2017-12-06T11:38:24.124Z"
}

The root fields are as follows:

JSON Params Description

id

Unique id of the command

targetDeviceId

Targeted device identifier

request

Command request (Cf. command request format)

response

Optional. Command response from device

status

Status of the command. Please refer to Command status for more details.

deliveryStatus

Optional. Delivery status of the command. Please refer to Delivery status for more details.

errorCode

Optional. Error code encountered during command processing.

policy

Policy for the command (Cf. Policy format)

history

Contains the history of changes in the status of the command. (Cf. Command history)

created

Registration date of the command

updated

Last "status" update date of the command.


The format of a command request is the following:

JSON Params Description

connector

connector/protocol to use to forward the command. Allowable values: mqtt, lora, sms or x-connector.

value

command value (protocol/connector-dependant) (Cf. MQTT value, LoRa® value, SMS value, External connector value)


The format of the policy for a command is the following:

JSON Params Description

expirationInSeconds

Optional. expiration in seconds since command creation date. Default is no expiry. Min value is 5 seconds (Cf. Expiration Timeout).

ackTimeoutInSeconds

Optional. acknowledgement timeout in seconds since command is being processed. Default depends on connectiviy. Min value is 10 seconds (Cf. Acknowledgement Timeout).

ackMode

Optional. Ack mode for this command. Please refer to Acknowledgement level for more details.

attempts

Optional. Number of attempts in case of ERROR. Default to 1 Please refer to Attempts number for more details.


The format of the history for a command is an array of this:

JSON Params Description

timestamp

Timestamp of this event

status

Status of the command at that moment

deliveryStatus

Optional. Delivery status of the command at that moment

errorCode

Optional. Error code encountered during command processing.

nodeId

Optional. NodeId of the interface used to process the command


8.3.10. Command registering by connector

For each kind of connectivity, the command registering uses specific values, the final delivery status is also different according to acknowledgement level.

8.3.10.1. Case of MQTT
To see how the commands are processed by device and to learn more, see the command section "device mode"
8.3.10.1.1. Delivery status behaviour according to acknowledgement level
Acknowledgment NONE (just sent the command) APPLICATIVE (waiting for response to validate)

Description

MQTT connector sent the command through open connection

Applicative response from device (default value)

Sequence of events & evolution of the statuses

Interactive

Interactive

Final Success Delivery Status

SENT

REPLIED

Default acknowledgement timeout

-

24h (7 days with v0 API), and the maximal value is 7 days.

8.3.10.1.2. Values for command registration

Value field can be any valid JSON Interactive

JSON Params Description

req

the command in string format

arg

List of parameters. Should not contain field name with . character or start with $ character

Example: Let’s take the case of a command recorded for a device with an online MQTT interface, with an APPLICATIVE acknowledgement level.

{
    "request": {
        "connector": "mqtt",
        "value": {
            "req": "reboot",
            "arg": {
                "delay": 1000
            }
        }
    },
    "policy": {
        "expirationInSeconds": 120,
        "ackMode": "APPLICATIVE"
    }
}

Please refer to the MQTT device mode part for messages that your device can send or receive.

To see an example, go to MQTT Command Example section.
8.3.10.2. Case of LoRa®
8.3.10.2.1. Delivery status behaviour according to acknowledgement level
Acknowledgment NONE (just sent the command) NETWORK (waiting for network/protocol ack)

Description

Downlink report received (default value)

Downlink acknowledge received

Sequence of events & evolution of the statuses

Interactive

Interactive

Final Success Delivery Status

SENT

REPLIED

Default acknowledgement timeout

-

For LoRa®, the acknowledgement timeout cannot be defined by the customer, and is correlated with the device traffic: the LoRa® connector waits maximum 3 uplinks to get an ACK bit set to 1. Beyond that, the acknowledgement timeout is reached

8.3.10.2.2. Values for command registration

Interactive

Value field in request command sets the following parameters:

JSON Params Description

data

hexadecimal raw data of the command

port

port of the device on which the command will be sent (1 to 254)

Example:

{
    "request": {
            "connector":"lora",
            "value":{
                    "data": "A1FF20",
                    "port": 1
            }
    },
    "policy": {
            "expirationInSeconds" : 200,
            "ackMode": "NONE"
    }
}
To see an example, go to LoRa® Command Example section.
8.3.10.3. Case of SMS
8.3.10.3.1. Delivery status behaviour according to acknowledgement level
Acknowledgment NONE (just sent the command)

Description

Message sent (default value)

8.3.10.3.2. Values for command registration

Interactive

Value field in request command sets the following data:

JSON Params Description

payload

message to send

TEXT : size max 160 characters and GSM 7 compatible characters (for more information, see GSM 03.38 standard or chapter 6.2.1 of www.etsi.org/deliver/etsi_gts/03/0338/05.00.00_60/gsmts_0338v050000p.pdf)

BINARY : size max 260 characters (140 octets) and hexadecimal characters

serverPhoneNumber

server phone number. Must be defined in the offer settings

type

message format in TEXT or BINARY

Example:

{
    "request": {
            "connector": "sms",
        "value": {
            "payload": "Hello Live Objects!",
            "type": "TEXT",
            "serverPhoneNumber": "20406"
        }
    },
    "policy": {
            "expirationInSeconds" : 30,
            "ackMode": "NONE"
    }
}
To see an example, go to SMS Command Example section.
8.3.10.4. Case of External connector
8.3.10.4.1. Delivery status behaviour according to acknowledgement level
Acknowledge required NONE (just sent the command) APPLICATIVE (waiting for response to validate)

Description

External connector sent the command through open connection

Applicative response from device (default value)

Sequence of events & evolution of the statuses

Interactive

Interactive

Final Success Delivery Status

SENT

REPLIED

Default acknowledgement timeout

-

For External connector, the default value of acknowledgement timeout is 24h, and the maximal value is 7 days. Beyond that, the acknowledgement timeout is reached

8.3.10.4.2. Values for command registration

Interactive

Value field in request command can be any valid JSON. It can contain a map of 100 entries maximum. Each entry can contain 255 characters maximum.

Example: Let’s take the case of a command recorded for a device with an online external connector interface, with an APPLICATIVE acknowledgement level.

{
    "request": {
      "connector": "x-connector",
      "value": {
        "myCommand": "turn on",
        "myParams": {
          "device": "6"
        }
      }
    },
    "policy": {
      "expirationInSeconds": 60,
      "ackMode": "APPLICATIVE"
    }
  }

8.3.11. Command examples by connector

8.3.11.1. Example for Mqtt

Let’s take the example of a smart lock, connected to Live Objects with an MQTT interface.

8.3.11.1.1. Description

From your smartphone, you want to unlock your door for a family member who forgot his keys. The application on your phone will create a command on Live Objects, who will send it to the door

  • You want to know if your unlock request has been well executed.

  • You need to set the maximum waiting time for your order to be executed : 2 minutes here, not three hours due to a connectivity issues.

To do this, you must :

  • Have smartphone business application connected to LO.

  • A smart lock system online who subscribe to the topic dev/cmd on Live Objects

  • Your device must support command capability (check the device before beginning).

Then apply this steps :

  • Send a command request.

  • Wait the processing time

  • Check the result from your smartphone.

8.3.11.1.2. Command request details

Your smartphone have to send the following request to LO :

API : POST /api/v1/deviceMgt/devices/<deviceId>/commands

Request sample :

{
    "request": {
        "connector": "mqtt",
        "value": {
            "req": "unlock",
            "arg": {
                "delay": 1000
            }
        }
    },
    "policy": {
        "expirationInSeconds": 120, (1)
        "ackMode": "APPLICATIVE"    (2)
        "ackTimeoutInSeconds": 180, (3)
    }
}
1 When you register a command you must set the expiration timeout, to fix a limit delay for PENDING/RETRYING status, this means that once the command has been registred, Live Objects will wait for a device subscription to the corresponding topic under this delay. Once this delay exceeded without new event from the device, the command status change automatically to EXPIRED.
2 Depending on the acknowledgement level you have set, Live Objects will wait for a response from the smart lock.
3 If you have set the ackMode to applicative, you can also override the acknowledgement timeout to limit the maximum response time allowed to the device. In this case, we choose an APPLICATIVE acknowldegment level, so a response from the device is mandatory.
8.3.11.1.3. Process of the successful case

Interactive

8.3.11.1.4. Timeouts during the process

Two kind of timeouts can happen : Expiration & Acknowledgment timeouts.

Interactive

8.3.11.1.5. Check the status of the command

At anytime during process, you can check the command status or get the whole command

Interactive

API : GET /api/v1/deviceMgt/commands/{commandId}/status

Response :

{
"content": "PROCESSED"
}

Response for the entire command, the request is the same but use another endpoint

API : GET /api/v1/deviceMgt/commands/<commandId>

Response :

{
    "id": "ae49129f-9ce4-4782-82c4c6a2",
    "targetDeviceId": "urn:lo:nsid:smartlock:123456",
    "request": {
        "connector": "mqtt",
        "value": {
            "req": "unlock",
            "arg": {
                "delay": 1000
            }
        }
    },
    "response": {
        "done": true
    },
    "status": "PROCESSED",
    "deliveryStatus": "REPLIED",
    "policy": {
        "expirationInSeconds": 120,
        "ackTimeoutInSeconds": 180,
        "ackMode": "APPLICATIVE"
    },
    "history": [
        {
            "timestamp": "2017-12-06T11:32:25.055Z",
            "status" : "PENDING"
        }, {
            "timestamp": "2017-12-06T11:38:22.481Z",
            "status": "PROCESSING",
            "deliveryStatus": "SENT",
            "nodeId": "abcd123456"
        }, {
            "timestamp": "2017-12-06T11:38:24.124Z",
            "status": "PROCESSED",
            "deliveryStatus": "REPLIED",
            "nodeId": "abcd123456"
        }
    ],
    "created": "2017-12-06T11:32:25.055Z",
    "updated": "2017-12-06T11:38:24.124Z"
}
8.3.11.2. Example for LoRa®

Let’s take the example of a smart sensor of water metering, connected to Live Objects with LoRa® interface.

8.3.11.2.1. Description

The objective is to monitor a water usage monthly. To do this, you must :

  • Send a "reset to zero" command to the water meter at the end of the month.

    • The command will be sent in a binary format supported by LoRa® connectivity.

  • Have water meter system connected to Live Objects with LoRa® interface.

Then apply this steps :

  • Register command through Live Objects portal or your business application.

  • Follow the command status during the operation.

  • Check the result

The LoRa® devices has a low energy consumption as well as sleeping time is relatively long. So, the command request takes time to be processed. The expiration timeout must be set with high values.
8.3.11.2.2. Command processing policy

-Set your command processing policy before registering_

POST /api/v1/deviceMgt/devices/urn:lo:nsid:lora:watermeter123/commands

{
    "request": {
        "connector": "lora",
        "value": {
            "data": "44D2F0",
            "port": "125"
        }
    },
    "policy": {
        "expirationInSeconds": 28800,  (1)
        "ackMode": "NETWORK"           (2)
    }
}
1 The expiration timeout can be setted to replace the default limit delay for PENDING/RETRYING status.
2 Depending on the acknowledgement level setted, Live Objects will wait for a response from the water meter. In this case, we choose a NETWORK acknowldegment level, so a response from the LoRa® network is mandatory.

The acknowledgment timeout can’t be setted by the customer

8.3.11.2.3. Process of the successful case

Interactive

8.3.11.2.4. Timeouts during the process

Two kind of timeouts can happen : Expiration & Acknowledgment timeouts.

Interactive

8.3.11.3. Example for SMS

We return to the example presented previously of a smart lock with the MQTT interface, in this example we have connected our Unlock system to Live Objects with an SMS interface.

Now we register a command through an SMS interface and Live objects will be sent this command with an SMS message to connected device.

8.3.11.3.1. Register command
POST /api/v1/deviceMgt/devices/urn:lo:nsid:sms:unlock123/commands
{
    "request": {
      "connector": "sms",
      "value": {
        "payload": "unlock",
        "type": "TEXT"
      }
    },
    "policy": {
        "expirationInSeconds": 60,  (1)
        "ackMode": "NONE"           (2)
    }
 }
1 When you register a command you must set the expiration timeout, to fix a limit delay for PENDING/RETRYING status, this means that once the command has been registred, Live Objects will wait until the request was sent. Once this delay exceeded, the command status change automatically to EXPIRED. (This can happen if you have paused your SMS interface for exemple) In this case, after 60 seconds waiting, Live Objects change the status of the command at EXPIRED.
2 When your device use SMS interface, only ackMode NONE is supported.
8.3.11.3.2. Register a binary command

The same example with a binary command

POST /api/v1/deviceMgt/devices/urn:lo:nsid:sms:unlock123/commands
{
    "request": {
      "connector": "sms",
      "value": {
        "payload": "756e6c6f636b", (1)
        "type": "BINARY"           (2)
      }
    },
    "policy": {
        "expirationInSeconds": 60,
        "ackMode": "NONE"
    }
 }
1 Payload in hex format, converted from string = "unlock".
2 Payload type must be set with value = BINARY

8.4. Resources

Currently, APIs allow to manage resource update only for MQTT connector.

8.4.1. Principle

A resource is a versioned binary content (for example a device firmware). You can manage a repository of resources in your tenant account. For each resource you can manage multiple resource version.

Live Objects can track the current versions of resources on a specific device.

You can set the target version of resources for a specific device in Live Objects that will then try to update the resources on the device as soon as the device is available for resource update.

Compatibility restrictions can be configured between versions to avoid compatibility issues when switching from a version to another. Live Objects will refuse a resource update request that don’t match the compatibility restrictions.

Device resource update steps

Interactive

  • step 1: the device (or the codec communicating on its behalf) notifies Live Objects of its current resources and versions.

  • step 2 Live Objects compares it with the expected resource version

  • step 3 Live Objects waits for the availability of the device resource capability.

  • step 4 when the device is ready, Live Objects fetchs the resource version binary and generate a download link.

  • step 5 Live Objects sends the download link and resource version id to the device

  • step 6 optional the device can respond to indicate it accepts or not the new resource version.

  • step 7 the device can download the binary.

  • step 8 optional at anytime, the operation can be cancelled. The download link will be removed by Live Objects

  • step 9 optional at this point the device can send a personalize error. The operation will be stated as failed

  • step 10 the device can check the file integrety using the provided md5

  • step 11 to acknowledge the binary reception, the device sends a new current resources message.

  • step 12 Live Objects compares the current and expected resource version and update the operation status

8.4.2. Connectors

In order to send the binary content to a device, Live Objects is built to provide different type of transfert protocols. Those protocols are handled by connectors. Connectors can support configuration parameters called metadata.

At this time, Live Objects only provides an http-updater that allows the device to download the resource using HTTP protocol.

http-updater supports the metadata "secured" to enable https link for resources update, the default value is set to false (i.e http link). It is possible to set this "secured" metadata from device metadata, resource metadata or update operation metadata.

8.4.3. Status

Device resource update states

Interactive

If your device is connected in Device mode, please refer to the MQTT device mode part for messages that your device can send or receive.

8.4.4. Aliases

You can configure several aliases on a resource to help you manage your resource update operations. An alias can be used to replace with a string of your choice a resource version when requesting a new target for a resource. You can use up to 5 aliases per resource A same version can be used in several aliases An alias key must be unique

Here is an example to use an alias.

8.4.5. Examples

8.4.5.1. Set device resource version

Request

POST /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/resources/MyResource001
{
    "version": "1.0",
    "metadata" : {
        "secured" : true
    }
}

Response

{
  "reported": {
    "version": "1.0",
    "timestamp": "2020-03-12T10:43:18.350Z"
  },
  "requested": {
    "version": "1.1",
    "timestamp": "2020-07-23T14:53:03.959Z"
  }
}
JSON Params Description

reported

current device resource status

requested

requested resource status

version

resource version

timestamp

date of resource version association

metadata

metadata associated with this device (if any)

8.4.5.2. Set device resource version using alias
8.4.5.2.1. Configure an alias

Request

PUT /api/v0/rm/MyResource001
{
  "connector": "http-updater",
  "metadata": {
    "secured": true
  },
  "versionAliases" : {
      "prod" : "1.1",
      "preprod" : "1.2"
  }
}

Response

{
  "resourceId" : "MyResource001",
  "connector" : "http-updater",
  "metadata" : {
    "secured" : "true"
  },
    "versionAliases" : {
      "prod" : "1.1",
      "preprod" : "1.2"
  },
  "creationTs" : 1563191282476,
  "updateTs" : 1595594676082
}
8.4.5.2.2. Set target version

Request

POST /api/v1/deviceMgt/devices/urn:lo:nsid:sensor:temp001/resources/MyResource001
{
    "version": "prod",
    "metadata" : {
        "secured" : true
    }
}

Response

{
  "reported": {
    "version": "1.0",
    "timestamp": "2020-03-12T10:43:18.350Z"
  },
  "requested": {
    "version": "1.1",
    "timestamp": "2020-07-23T14:53:03.959Z"
  }
}

The requested alias must exist and meet the compatibility restrictions

8.5. Campaign management

Campaign management is a Live Objects feature that allows a fleet manager to schedule execution of device management operations on a large number of devices.

The following operations are supported in a campaign definition:

  • configuration,

  • commands,

  • resource update.

8.5.1. Campaign creation

When creating a campaign, the user must provide the following information:

name

A short name to identify the campaign

description

(optional) Detailed description of the campaign

options

(optional) Set of campaign options.

planning

The scheduling configuration including the start date and the end date for the campaign

targets

Devices targeted: either idList or filterQuery (exclusively). cf. Campaign targets

operations

A sequence of operations that will be executed on each device of the campaign.

Campaigns are created from the REST API by providing a campaign definition with properties described previously.

Campaigns management are available for all types of devices (MQTT, LoRa®, SMS and External connector), for all connectivity, however you must take into consideration the capabilities and the conformity of the configurations, commands and resource that you push in your campaigns. Make sure that the devices support the requests that you send through connectors and through the networks. For normal use, only one connectivity is targeted by the filters or by the list of device id’s.
8.5.1.1. Campaign options

Campaign options section could be empty or omitted.

Example of campaign options:

"options": {
    "dynamicallyAddEligibleDevice": true
  }

Options are:

  • dynamicallyAddEligibleDevice (default: false).

    • Set this option to true to dynamically enroll devices to the campaign. During the campaign planning, new or updated devices could be dynamically enrolled if they match the filterQuery.

    • This option requires a filterQuery target definition.

    • A campaign with dynamicallyAddEligibleDevice option will always be in running state until end date,

whereas others (non-dynamics) campaigns could end as soon as all devices operations ended or end date reached.

8.5.1.2. Campaign operations

A campaign includes one or more operations:

For each device, operations are executed one after the other, each operation waits for the success of the previous operation.

All operations definitions could embed an optional maxRetry attribute:

  • default is 0, and max is 5.

  • In case of operation failure, operation will be retried in the limit of maxRetry.

If an operation fails after maxRetry attempts (or is canceled) for a device, the remaining operations are not executed for this device and the sequence ends in failure (or in canceled status).

8.5.1.3. Config operation

Example of config operation definition:

  {
     "action":"configure",
     "definition":{
        "assetParameters":{
           "param1":{
              "type":"INT32",
              "valueInt32":1234
           }
        },
        "maxRetry": 1
     }
  }
action
  • configure action will send to the device one or many "parameters" to update.

definition
  • assetParameters has the same format as the corresponding unitary device management operation: Device configuration.

  • maxRetry (optional) defines how many retries should be executed in case of failure of the current operation.

The following table shows how the config operation statuses are converted into sequence statuses

Config operation status

Resulting status in the sequence

PENDING

if it is the first operation: PENDING, if not: IN_PROGRESS

SENT

IN_PROGRESS

CANCELED

CANCELED

OK

if it is the last operation: SUCCESS, if not: PENDING and the sequence moves onto the next operation

FAILED

FAILURE

8.5.1.4. Command operation

Example of command version 1 operation definition:

  {
    "action":"command",
    "version":1,
    "definition":{
      "request": {
        "connector": "mqtt",
        "value": {
          "req": "rebootV1",
          "arg": {
             "delay": 1000
          }
        }
      },
      "policy": {
        "expirationInSeconds": 120,
        "ackMode": "APPLICATIVE"
      },
      "maxRetry": 0
    }
  }
action
  • command action will register (and send) a command to the device.

definition
  • this section uses the same format as the corresponding unitary device management operation: Commands.

  • maxRetry (optional) defines how many retries should be executed in case of failure of the current operation.

The following table shows how the command operation statuses are converted into sequence statuses

Command operation status

Resulting status in the sequence

PENDING

if it is the first operation: PENDING, if not: IN_PROGRESS

PROCESSING

IN_PROGRESS

PROCESSED

if it is the last operation: SUCCESS, if not: PENDING and the sequence moves onto the next operation

CANCELED

CANCELED

ERROR

FAILURE

EXPIRED

FAILURE

UNKNOWN

FAILURE

8.5.1.5. Resource operation

Example of resource operation definition:

{
  "action": "resource",
  "definition": {
    "resourceId": "X11_firmware",
    "targetVersion": "2.1",
    "maxRetry": 4,
    "metadata" : {
        "secured" : true
    }
  }
}
action
  • resource action will send a resource update request to the device.

definition
  • resourceId identifies the resource to update

  • targetVersion is the new version of the resource to download and install. Aliases can also be used but the resolution of the version will be made for each operations when sent to the Device Manager. In other words, modifications on an alias that is used in a running campaign can affect the target version of the campaign.

  • maxRetry (optional) defines how many retries should be executed in case of failure of the current operation

  • metadata (optional) is the metadata associated with this resource update request The following table shows how the resource operation statuses are converted into sequence statuses

Resource operation status

Resulting status in the sequence

PENDING

if it is the first operation: PENDING, if not: IN_PROGRESS

PREPARING_CONNECTOR

if it is the first operation: PENDING, if not: IN_PROGRESS

PREPARING_ASSET

IN_PROGRESS

WAITING_TRANSFER_INFO

IN_PROGRESS

TRANSFER_PENDING

IN_PROGRESS

TRANSFER_IN_PROGRESS

IN_PROGRESS

TRANSFER_SUCCESS

IN_PROGRESS

DONE

if it is the last operation: SUCCESS, if not: PENDING and the sequence moves onto the next operation

ERROR

FAILURE

CANCELED

CANCELED

8.5.1.6. Campaign target (idList)

Campaign devices targets: either idList or filterQuery (exclusively).

idList is a flat list of devices identifiers.

Devices are identified using a URN identifier.

The format of this identifier must be urn:lo:nsid:{ns}:{id} with

  • ns the target device identifier namespace

  • id the target device identifier

idList is not compatible with dynamicallyAddEligibleDevice option.

Below is an example of campaign targets definition using idList:

   "targets":{
      "idList":[
         "urn:lo:nsid:namespace:device1",
         "urn:lo:nsid:namespace:device2"
      ]
   }
8.5.1.7. Campaign target (filterQuery RSQL)

filterQuery: use RSQL to target devices.

Below is an example of campaign targets definition using filterQuery:

  "targets": {"filterQuery": "groupPath==/"}
Table 2. RSQL Semantic Table
desc syntax

Logical AND

; or and

Logical OR

, or or

Equal to

==

Not equal to

!=

Less than

=lt= or <

Less than or equal to

=le= or

Greater than operator

=gt= or >

Greater than or equal to

=ge= or >=

In

=in=

Not in

=out=

Below are example of filterQuery values.

  • Filter using tags

tags=in=(FUT,TEST1)

For example, devices with at least tags "FUT" and "TEST1" whatever the order or additional tags

  • Filter on properties

properties.mykey=in=(enum1, enum3)
properties.mykey==toto
  • Filter on groups

groupID=in=(1224,1234)
groupID==1234
groupPath=in=(/FR, /EN)
8.5.1.8. Campaign creation examples

Below are examples of campaign definition:

Set parameter "param1" to value 1234 on two devices
POST /api/v0/deviceMgt/campaigns
{
   "name":"campaign1",
   "description":"A campaign that configures parameters",
   "planning":{
      "startDate":"2017-07-01T00:00:00Z",
      "endDate":"2017-07-23T23:59:59Z"
   },
   "targets":{
      "idList":[
         "urn:lo:nsid:namespace:device1",
         "urn:lo:nsid:namespace:device2"
      ]
   },
   "operations":[
      {
         "action":"configure",
         "definition":{
            "assetParameters":{
               "param1":{
                  "type":"INT32",
                  "valueInt32":1234
               }
            }
         }
      }
   ]
}
Send a reset command with a delay parameter for devices with foo tag
POST /api/v0/deviceMgt/campaigns
{
   "name":"campaign2",
   "description":"A campaign that sends a command",
   "planning":{
      "startDate":"2017-07-01T00:00:00Z",
      "endDate":"2017-07-23T23:59:59Z"
   },
   "options": {
    "dynamicallyAddEligibleDevice": true
   },
   "targets": {"filterQuery": "tags=in=(foo)"},
   "operations":[
      {
         "action":"command",
         "definition":{
            "event":"reset",
            "data":{
               "delay":"5000"
            }
         }
      }
   ]
}
Update the resource firmware.bin to version 1.1 (with 2 retries max)
POST /api/v0/deviceMgt/campaigns
{
   "name":"campaign3",
   "description":"A campaign that updates a resource",
   "planning":{
      "startDate":"2017-07-01T00:00:00Z",
      "endDate":"2017-07-23T23:59:59Z"
   },
   "targets":{
      "idList":[
         "urn:lo:nsid:namespace:device1",
         "urn:lo:nsid:namespace:device2"
      ]
   },
   "operations":[
      {
         "action":"resource",
         "definition":{
            "resourceId":"firmware.bin",
            "targetVersion":"1.1",
            "maxRetry": 2,
            "metadata" : {
                 "secured" : true
            }
         }
      }
   ]
}

8.5.2. Campaign reporting

Once a campaign is created, a fleet manager can monitor the state of a campaign.

A campaign can have one of the statuses described below:

SCHEDULED

The campaign has not yet started

RUNNING

The campaign is in progress

COMPLETE

The campaign is finished and all devices ended their sequence in success

INCOMPLETE

The campaign is finished but some devices could not be configured

SERVER_ERROR

An internal error occurred in the platform and the campaign could not be completed

CANCELING

The campaign is waiting for running sequences to end, sequences that have not started yet will not start

CANCELED

The campaign was canceled and some devices might not have been configured

The possible statuses for a device are presented below:

notStarted

No operation executed on the device

pending

The operation is recorded and waiting to be process by the device (soft cancel is still possible)

inProgress

The operation is being processed by the device (soft cancel is no more possible)

success

All operations were successfully executed on the device

failure

One operation of the sequence failed, so the remaining operations (if any) were not executed

canceled

The sequence was canceled before the end of all operations

8.5.2.1. Campaign cancelation

A campaign can be canceled with the following REST API endpoint:

PUT /api/v0/deviceMgt/campaigns/{campaignId}/cancel

If the campaign is already running, canceling it will set its state to CANCELING and the campaign will cancel pending sequences and wait for in progress sequences to end. Then the campaign state will switch to CANCELED.

To abort in progress sequences, the force flag can be used.

PUT /api/v0/deviceMgt/campaigns/{campaignId}/cancel
force = true
8.5.2.2. Campaign deletion

A campaign can be deleted with the following REST API endpoint:

DELETE /api/v0/deviceMgt/campaigns/{campaignId}

If the campaign is in RUNNING or CANCELING state, it cannot be deleted. In this case the force flag can be used to execute a forced cancelation and automatically delete the campaign once it is in CANCELED state.

DELETE /api/v0/deviceMgt/campaigns/{campaignId}
force = true

8.5.3. Global report

The global report indicates the campaign definition, the current status of a campaign and statistics about the number of devices with a given status.

Get global status of a speficied campaign
GET /api/v0/deviceMgt/campaigns/{campaignId}
{
   "name":"campaign1",
   "description":"A campaign that configures parameters",
   "planning":{
      "startDate":"2017-07-01T00:00:00Z",
      "endDate":"2017-07-23T23:59:59Z"
   },
   "targets":{
      "idList":[
         "urn:lo:nsid:namespace:device1",
         "urn:lo:nsid:namespace:device2"
      ]
   },
   "operations":[
      {
         "action":"configure",
         "definition":{
            "assetParameters":{
               "param1":{
                  "type":"INT32",
                  "valueInt32":1234
               }
            }
         }
      }
   ],
   "numberOfTargets":2,
   "totalTargetsPerStatus":{
      "notStarted":0,
      "pending":0,
      "inProgress":1,
      "failed":0,
      "success":1,
      "canceled":0
   },
   "campaignStatus":"RUNNING",
   "created":"2017-06-01T00:00:00Z",
   "updated":"2017-07-01T00:00:00Z"
}

8.5.4. Detailed report

The detailed report gives the status of each device in a campaign. The status property gives the status for the whole sequence of operations. The detailed report also indicates the status of each operation (operation reports are ordered just like in the campaign definition).

operationStatus

Exact status reported by the device manager (the list of possible values depends on the type of operation). A special value notStarted is used when the operation is not yet started.

operationId

Identifier returned by the device manager when the campaign manager created the operation

started

Date when the operation was started

updated

Last time the operation report was updated

ended

Date when the operation was finished

currentRetry
  • (Option) Retry attempt count of the latest operation executed.

  • For example, an operationStatus equals to OK (or DONE) and currentRetry equals to 1 means that operation first failed, but the first retry attempt was a success.

Get global status of a speficied campaign
GET /api/v0/deviceMgt/campaigns/{campaignId}/targets
{
   "page":0,
   "size":10,
   "totalCount":2,
   "data":[
      {
         "device":"urn:lo:nsid:namespace:id1",
         "status":"inProgress",
         "created":"2017-07-01T16:12:21.000Z",
         "updated":"2017-07-01T16:12:21.000Z",
         "operations":[
            {
               "action":"configure",
               "operationStatus":"OK",
               "started":"2017-07-01T16:20:21.000Z",
               "updated":"2017-07-01T16:25:21.000Z",
               "ended":"2017-07-01T16:25:21.000Z"
            },
            {
               "action":"command",
               "operationStatus":"SENT",
               "operationId":"12345",
               "started":"2017-07-01T16:30:21.000Z",
               "updated":"2017-07-01T16:31:21.000Z"
            },
            {
               "action":"resource",
               "operationStatus":"notStarted"
            }
         ]
      },
      {
         "device":"urn:lo:nsid:namespace:id2",
         "status":"success",
         "created":"2017-07-01T16:12:21.000Z",
         "updated":"2017-07-01T16:12:21.000Z",
         "operations":[
            {
               "action":"configure",
               "operationStatus":"OK"
               "started":"2017-07-01T16:20:21.000Z",
               "updated":"2017-07-01T16:25:21.000Z",
               "ended":"2017-07-01T16:25:21.000Z"
            },
            {
               "action":"command",
               "operationStatus":"PROCESSED",
               "operationId":"6789",
               "started":"2017-07-01T16:30:21.000Z",
               "updated":"2017-07-01T16:31:21.000Z"
            },
            {
                "action": "resource",
                "operationStatus": "DONE",
                "operationId": "X11_firmware",
                "started": "2017-07-01T16:30:21.000Z",
                "updated": "2017-07-01T16:38:21.000Z",
                "ended": "2017-07-01T16:38:21.000Z",
                "currentRetry": 1
            }
         ]
      }
   ]
}

9. Devices Inventory Explorer

9.1. Introduction

The inventory explorer present two API :

  • stats: provides a way to count devices or device components within the whole fleet. Results can be filtered and grouped by different criteria, which allows to build various aggregated views on devices data. For instance, a stats query can get the total number of devices with a specific connectivity and within a specific device group, while providing a separate count under each of their possible interface status.


stats-widget-example
Figure 1. Dashboard view of LoRa devices within the "Paris" group, grouped by connectivity status


  • search: provides a way to detail devices or device components within the whole fleet. Results can be filtered by different criteria.

In order to make these views possible, the inventory service maintains an indexed version of the whole fleet, each document representing an enriched version of a Live Objects device. The device’s static properties and most of the events occurring during its lifecycle are saved as part of an extended device state. As a consequence, a latency of a few seconds has to be expected before the current state of the fleet is available in the inventory index, this latency can be longer especially when dealing with very large fleets. However, as with most Live Objects APIs, eventual consistency is guaranteed, meaning that if all activity ceased on devices, the inventory index will eventually end up in sync with the fleet state.

9.2. Common filters

Both inventory explorer APIs use the same kind of filtering by location with geoBounds or globally with queryString.

9.2.1. Filter queries

The format of a query matches the following pattern:

{
    "filters": {
      "geoBounds": {...},
      "queryString": "..."
    }
}

9.2.2. Global filters

Filtering on location

{
    "filters": {
        "geoBounds": {
            "topLeft": {
                "lat": 50.56789,
                "lon": 1.10101
            },
            "bottomRight": {
                "lat": 12.34567,
                "lon": 20.20202
            }
        }
    }
}

Select all devices within the coordinates boundaries.

Filtering using RSQL notation

Filtering expression using RSQL notation and should not exceed 512 characters.

This syntax permits mixing several patterns according to allowed fields (see following table).

Supported fields Description

name

{
    "queryString": "name=='my Device'"
}

device name

id

{
    "queryString": "id==myId"
}

device identifier

group.path

{
    "queryString": "group.path==/foo/bar"
}

group path

group.id

{
    "queryString": "group.id==myGroupId"
}

group identifier

tags

{
    "queryString": "tags=in=(spain, v2)"
}

tags

properties.k

{
    "queryString": "properties.k==myKey"
}

properties key

properties.v

{
    "queryString": "properties.v==myValue"
}

properties value

properties

{
    "queryString": "properties=q='k==myKey and v==myValue'"
}

properties (associated with =q= operator)

property

{
    "queryString": "property.myKey==myValue"
}

properties (associated with key value)

interfaces

{
    "queryString": "interfaces=q='connector==lo*'"
}

interfaces (associated with =q= operator)

interfaces.connector

{
    "queryString": "interfaces.connector==mqtt"
}

interface connector type (Ex: sms, lora, mqtt)

interfaces.nodeId

{
    "queryString": "interfaces.nodeId==myNodeId"
}

interface node identifier

interfaces.enabled

{
    "queryString": "interfaces.enabled==false"
}

interface activation state (true or false)

interfaces.status

{
    "queryString": "interfaces.status!=OFFLINE"
}

interface status (REGISTERED, INITIALIZING, INITIALIZED, REACTIVATED, ONLINE, ACTIVATED, OFFLINE, DEACTIVATED, CONNECTIVITY_ERROR, UNKNOWN)

interfaces.definition.profile

{
    "queryString": "interfaces.definition.profile==Generic_v2"
}

interface profile (for Lora)

activities

{
    "queryString": "activities=q='state!=SILENT or ruleId==ac*'"
}

activities (associated with =q= operator)

activities.ruleId

{
    "queryString": "activities.ruleId==myRuleId"
}

activities rule identifier

activities.state

{
    "queryString": "activities.state==ACTIVE"
}

activities state (UNKNOWN, SILENT, ACTIVE)

aggregatedActivityState

{
    "queryString": "aggregatedActivityState==ACTIVE"
}

activity state (UNKNOWN, SILENT, ACTIVE) aggregated all activities state of the device

This syntax permits mixing several filters according to allowed logical and comparison operators (see the following table).

Supported operators Description

==

{
    "queryString": "name==my Device"
}

equality

==<value>*

{
    "queryString": "id==my*"
}

means search for all id starting with 'my' characters

equality with prefix

!=

{
    "queryString": "group.path!=/foo/bar"
}

means search for all group paths different from '/foo/bar'

different

=q=

{
    "queryString": "properties=q='k==myKey and v==myValue'"
}

means search for all properties with key equals to 'myKey' and value equals 'myValue'.

equality only for activities, interfaces, properties nested fields

=in=

{
    "queryString": "tags=in=(spain, v2)"
}

means search for all tags equals to 'spain' or 'v2'.

group of possible values (corresponding to several 'or' operators)

and

{
    "queryString": "properties.k==myKey and tags!=demo"
}

logical and

;

{
    "queryString": "properties.k==myKey;tags!=demo"
}

identical to 'and' operator (other syntax)

or

{
    "queryString": "properties.k==myKey or tags!=demo"
}

logical or

,

{
    "queryString": "properties.k==myKey,tags!=demo"
}

identical to 'or' operator (other syntax)

RSQL complex syntax using (), '', " " can be executed:

We can regroup fields using parenthesis (by default 'and' operation is always rated first).

{
    "filters": {
        "queryString": "(tags==myTag or name==awesome*) and (group.path==/foo/* or properties=q='k==Version and v==\"my complete value\"' and interfaces.connector==lora)"
    }
}

The apostrophe character can be set using the \\.

{
    "filters": {
        "queryString": "tags=='Aujourd\\'hui'"
    }
}

All fields and values are case sensitive.

When search needs prefix value, only equality operator is accepted in this case.

Combinations of filters

Combining filters is supported. A "filters" section with multiple entries will result in all filters being applied concurrently during devices selection (by performing a logical AND between conditions).

{
    "filters": {
        "queryString": "interfaces.connector==lora",
        "geoBounds": {
            "topLeft": {
                "lat": 50.56789,
                "lon": 1.10101
            },
            "bottomRight": {
                "lat": 12.34567,
                "lon": 20.20202
            }
        }
    }
    }
}

Select all LoRa devices located inside the requested boundaries.

9.2.3. Device internal representation

As a reminder, the public model of a device, as exposed by the device management APIs, is fully described Cf. device object model. The inventory service maintains a slightly different version of this model, in order to provide additional information on devices and facilitate complex queries on their structure.

{
    "id": "urn:lo:nsid:lora:0004A30B001FE084",
    "name": "my device",
    "description": "this is my device",
    "tags": [
        "spain",
        "v2"
    ],
    "properties": [
        {
            "key": "prop1",
            "value": "val1"
        },
        {
            "key": "prop2",
            "value": "val2"
        }
    ],
    "groupId": "uyVhhN",
    "groupPath": "/foo/bar",
    "interfaces": [
        {
            "connector": "lora",
            "nodeId": "0004A30B001FE084",
            "definition" : {                        // Definition content is connectivity dependent
                "devEUI" : "0004A30B001FE084",
                "activationType" : "OTAA",
                "profile" : "Microchip RN2483",
                "encoding" : "StartKit",
                "connectivityOptions" : {
                    "ackUl" : false,
                    "tdoa" : false
                }
            },
            "enabled": true,
            "status": "ACTIVATED"
        }
    ],
    "connectors": ["lora"],
    "config": [],
    "resources": {},
    "location": {
        "lat": 48.8541822991324,
        "lon": 2.3463792646484762,
        "alt": 0.5,
        "accuracy": 10.0,
        "provider": "GPS",
        "lastUpdate": "2020-08-26T09:53:25.308Z",
    },
    "activityStates": [
        {
            "rule": {
                "id": "ec8a3217-7b3f-4020-b37b-133a65ad6384",
                "tags": [
                    "spain",
                    "v2"
                ]
            },
            "timestamp": "2020-08-26T09:53:25.308Z",
            "state": "SILENT"
        }
    ],
    "aggregatedActivityState": "SILENT",
    "lastDataCollected": "2020-08-27T09:51:25.301Z",
    "defaultDataStreamId": "stream1"
}

Note that a few fields have been added or modified with respect to the view provided by the device management services:

  • "connectors" is a flat list of all interfaces connectors

  • "lastDataCollected" marks the reception date of the most recent data received from the device

  • "properties" have been reorganized as a list of objects, so that their "key"s and "value"s can be accessed as fields

  • "activityStates" is a more complete view of the device’s activity. All states are available when the device is targeted by several activity rules.

  • "groupPath" is an alias for "group.path".

  • "groupId" is an alias for "group.id".

  • "location" is a record of the last known location of the device, with additional metadata.

  • "aggregatedActivityState" is a simplified activity state which regroups the list of activity rules (present in 'activityStates' field) in an unique state with the following logical :

Aggregated state

Description

SILENT

At least one activity rule is set to SILENT

ACTIVE

At least one activity rule is set to ACTIVE and none is set to SILENT

UNKNOWN

At least one activity rule is set to UNKNOWN and none is set neither to ACTIVE nor to SILENT

This version of device representation is not accessible by the API, but you can use the search API from the inventory explorer to get your device representation of inventory explorer version.

Example

POST /api/v1/deviceMgt/explorer/search
{
    "filters": {
        "queryString": "id==urn:lo:nsid:lora:0004A30B001FE084"
    }
}

Response

{
    "bookmark": [
        "urn:lo:nsid:lora:0004A30B001FE084"
    ],
    "devices": [
        {
            "id": "urn:lo:nsid:lora:0004A30B001FE084",
            "name": "my device",
            "description": "this is my device",
            "group": {
                "id": "uyVhhN",
                "path": "/foo/bar"
            },
            "tags": [
                "spain",
                "v2"
            ],
            "properties": [
                {
                "key": "prop1",
                "value": "val1"
            },
            {
                "key": "prop2",
                "value": "val2"
            }
        ],
        "interfaces": [
            {
            "connector": "lora",
            "nodeId": "0004A30B001FE084",
            "definition" : {
                "devEUI" : "0004A30B001FE084",
                "activationType" : "OTAA",
                "profile" : "Microchip RN2483",
                "encoding" : "StartKit",
                "connectivityOptions" : {
                    "ackUl" : false,
                    "tdoa" : false
                }
            },
            "enabled": true,
            "status": "ACTIVATED"
            "capabilities": {
                "configuration": {
                    "available": false
                },
                "command": {
                    "available": false
                },
                "resource": {
                    "available": false
                }
            },
            "activity": {
                "lastDlFcnt": 140,
                "lastUlFcnt": 12799,
                "lastDeactivationTs": "2019-10-23T09:06:10.898Z",
                "lastActivationTs": "2019-10-23T09:06:35.549Z",
                "lastSignalLevel": 1
            },
            "lastContact": "2019-11-28T03:58:38.429Z",
            "created": "2019-09-11T15:26:19.157Z",
            "updated": "2020-08-27T09:51:25.301Z"
            }
        ],
        "activities": [
            {
                "ruleId": "ec8a3217-7b3f-4020-b37b-133a65ad6384",
                "state": "SILENT"
            }
        ],
        "created": "2019-09-11T15:26:19.157Z",
        "updated": "2020-08-27T09:51:25.301Z"
        }
    ]
}

9.3. Statistics API

9.3.1. REST Endpoint

POST /api/v1/deviceMgt/explorer/stats

9.3.2. Filter queries

In addition to queries detailed in common filters, the format of a stats query matches the following pattern:

{
    "filters": {
      ...
    },
    "groupBy": {
      ...
    }
}

The global "filters" part retains only a matching subset of devices, and the groupBy clause contains the criteria that will provide the grouping keys for the aggregated sub-counters. When grouping by interface status, a typical response would look like this:

{
    "devices": 100,                     // devices count after applying global filters
    "fieldAggregation": {
        "count": 100,                   // total number of elements in aggregation buckets, here interfaces
        "devices": 100,                 // total number of devices in aggregation buckets
        "buckets": [
            {
                "key": "ONLINE",        // possible value of group key, here "interface status"
                "count": 85,            // elements count in this bucket
                "devices": 85           // devices count in this bucket
            },
            {
                "key": "OFFLINE",
                "count": 15,
                "devices": 15
            }
        ]
    }
}

The response contains several counters at three different levels:

  • global level: a total of all selected devices after filtering

  • aggregation level: the total number of devices and elements in all buckets

  • bucket level: the total number of devices and elements within each bucket

Note that each bucket contains two counters ("count" and "devices") that may hold different values depending on the grouping criterion. "Count" can hold the number of devices, interfaces, properties or activity states. For instance when grouping by interface status, "count" holds the number of interfaces matching the bucket key, while "devices" holds the effective number of devices with matching interfaces. This is because a given device may contain several interfaces, each with its own status. A device with two ONLINE interfaces would therefore contribute to the "devices" counter by 1, and to the "count" counter by 2.

This may happen each time an aggregation is requested on a nested component of the device. When this is not the case, "devices" is always equal to "count".

9.3.3. Global filters

The main filtering use the requests described in common filters chapter. The topmost "filters" clause selects a subset of devices, prior to any further aggregation.

9.3.4. Aggregations

9.3.4.1. Aggregation types

Two types of aggregations are supported: field aggregations and geolocation aggregations. In a field aggregation, the values of the bucket keys are taken from the possible values of the selected device’s field.

Field aggregation on tags

{
    "groupBy": {
        "field": "tags"
    }
}

Result

{
    "devices": 100,
    "fieldsAggregation": {
        "count": 100,
        "devices": 100,
        "buckets": [
            {
                "key": "spain",       // A tag value appearing in 25 devices within the fleet
                "count": 25,
                "devices": 25
            },
            ...
        ]
    }
}

A geolocation aggregation creates zone buckets. The size of each zone depend on the requested precision. A location bucket key is a coordinate object that marks the centroid of the bucket, i.e. the mean position of all the devices in the zone.

Geolocation aggregation

{
    "groupBy": {
        "location": {
            "precision": 5
        }
    },
    "options": {
      "includeGeoBoundsInBuckets": true
    }
}

Result

{
    "devices": 100,
    "geoAggregation": {
        "devices": 100,
        "buckets": [
            {
                "geoKey": {                     // centroid of devices positions within this bucket
                    "lat": 48.85418222285807,
                    "lon": 2.346379179507494
                },
                "geoBounds": {                  // if includeGeoBoundsInBuckets, geobound including all devices coordinates of the bucket
                    "topLeft": {
                        "lat": 48.85418226476759,
                        "lon": 2.3463791574827945
                    },
                    "bottomRight": {
                        "lat": 48.85418221085362,
                        "lon": 2.3463792633265257
                    }
                },
                "devices": 50
            },
           ...
        ],
      ...
    }
}
9.3.4.2. Aggregation levels

The API supports up to two levels of aggregations, which allows to break down the fleet using two different criteria. For instance the devices can be grouped by geographic zones, with interface status information being attached to the average position of each group.


2-levels-widget-example
Dashboard view of interface status by geographic zones


Nested aggregations

{
    "groupBy": {
        "location": {          // Field or geolocation aggregation
            "groupBy": {
                "interfaces": {           // Field aggregation only
                    "field": "status"
                }
            }
        }
    },
    "options": {
      "includeGeoBoundsInBuckets": true
    }
}

Result

{
    "devices": 30,
    "geoAggregation": {             // Top level geolocation aggregation
        "count": 30,
        "devices": 30,
        "buckets": [
            {
                "geoKey": {
                    "lat": 48.85418222285807,
                    "lon": 2.346379179507494
                },
                "geoBounds": {
                    "topLeft": {
                        "lat": 48.85418226476759,
                        "lon": 2.3463791574827945
                    },
                    "bottomRight": {
                        "lat": 48.85418221085362,
                        "lon": 2.3463792633265257
                    }
                },
                "devices": 30,
                "fieldAggregation": {       // Inner aggregation on interfaces status
                    "count": 30,
                    "devices": 30,
                    "buckets": [
                        {
                            "key": "ACTIVATED",
                            "count": 22,
                            "devices": 22
                        },
                        {
                            "key": "DEACTIVATED",
                            "count": 4,
                            "devices": 4
                        },
                        {
                            "key": "CONNECTIVITY_ERROR",
                            "count": 4,
                            "devices": 4
                        }
                    ]
                }
            }
        ],
        ...
    }
}

Note that field aggregations may appear at both levels, while geolocation aggregations may only appear at the topmost level.

9.3.5. Field aggregations

According to the internal model , the following aggregations can be used.

9.3.5.1. Supported aggregations

Field aggregations are only possible on a subset of the device’s fields, typically when these fields can hold common values among a number of devices.


Aggregation syntax Field names
{
    "groupBy": {
        "field": "<field name>"
    }
}

description, tags, group.path, aggregatedActivityState

{
    "groupBy": {
        "compositeField": "<field name>"
    }
}

connectors

{
    "groupBy": {
        "interfaces": {
            "field": "<field name>"
        }
    }
}

interface fields:

connector, status, definition.profile

{
    "groupBy": {
        "activityStates": {
            "field": "<field name>"
        }
    }
}

activityState fields:

state, rule.id

{
    "groupBy": {
        "properties": {
            "field": "<field name>"
        }
    }
}

property fields:

key, value

Note than when a field is located in a nested object (such as rule.id or definition.profile), both dot notation and object notation are supported. For instance, these notations are equally valid:

{
    "groupBy": {
        "activityStates": {
            "field": "rule.id"
        }
    }
}
{
    "groupBy": {
        "activityStates": {
            "rule": {
              "field": "id"
            }
        }
    }
}


9.3.5.2. Aggregations on lists

A regular field aggregation on a list will result in the creation of one bucket per element in the list. For instance a field aggregation on tags will build two buckets when processing a device with two tags.

A device with two tags

{
    "id": "urn:lo:nsid:foo:bar",
    "tags": [
        "spain",
        "v2"
    ],
    ...
}

Field aggregation on tags

{
    "groupBy": {
        "field": "tags"
    }
}

Result

{
    "devices": 1,
    "fieldAggregation": {
        "count": 1,
        "devices": 1,
        "buckets": [
            {
                "key": "spain",
                "count": 1,
                "devices": 1
            },
            {
                "key": "v2",
                "count": 1,
                "devices": 1
            }
        ]
    }
}

However, it is sometimes desirable for the buckets to reflect the actual values of devices lists, rather than their sparsed elements. For instance it should be possible to classify devices according to the combination of their interfaces, in order to differentiate mono-interfaces devices from multi-interfaces ones.

These composite buckets can be built by setting the "compositeField" property in the field aggregation.

Composite field aggregation on interface connectivities

{
    "groupBy": {
        "compositeField": "connectors"
    }
}

Result

{
    "devices": 7,
    "fieldAggregation": {
        "count": 7,
        "devices": 7,
        "buckets": [
            {
                "key": [
                    "lora"
                ],
                "count": 5,
                "devices": 5
            },
            {
                "key": [
                    "lora",
                    "sms"
                ],
                "count": 1,
                "devices": 1
            },
            {
                "key": [],
                "count": 1,
                "devices": 1
            }
        ]
    }
}

In this case buckets keys are list of values instead of simple strings. Among the 7 devices in the fleet, 5 are pure LoRa devices, 1 is a multi-interfaces LoRa+SMS device, and one has no declared interface so far.

9.3.6. Nested components

Some components of the device structure require a specific treatment within the aggregation API. Interfaces, properties, activityStates are all lists of objects detained by each device. Elements of these lists are referred to as nested components.

Aggregations on nested components fields

As a user of the aggregation API, one might expect two types of result when requesting an aggregation on a nested component field. For each result bucket, the API can count the number of devices that hold at least one nested component matching the bucket key. Alternatively, for each result bucket, the API can count the number of nested components matching the bucket key. For instance a device with two ONLINE interfaces can be counted once or twice in the aggregation result depending on these expectations. Actually, the inventory API does both, by providing two dedicated counters in its response.

Given the following aggregation:

{
    "groupBy": {
        "interfaces": {
            "field": "status"
        }
    }
}

If the whole fleet contains currently a single device with two ONLINE interfaces, the result would be:

{
    "devices": 1,
    "fieldAggregation": {
        "count": 2,
        "devices": 1,
        "buckets": [
            {
                "key": "ONLINE",
                "count": 2,
                "devices": 1
            }
        ]
    }
}

"count" is related to the number of interfaces, while "devices" is the effective number of devices. The same pattern applies to all other nested components.

9.3.7. Filters and nested components

Filters on nested components (interfaces, properties, activityStates, see global filters section) can be applied globally through queryString. When applied globally, these filters select all devices holding at least one matching nested component. If a device is selected, all its nested components contribute to the construction of response buckets, even if they dont match the filter individually.

Device with multiple properties

{
    "id": "urn:lo:nsid:foo:bar",
    "name": "my device",
    "properties": [
        {
            "key": "prop1",
            "value": "val1"
        },
        {
            "key": "prop2",
            "value": "val2"
        }
    ],
  ...
}

Using a global filter on a matching property key selects this device and all its properties.

Global filter on property key

{
    "filters": {
        "queryString": "properties.k==prop1"
    },
    "groupBy": {
        "properties": {
            "field": "value"
        }
    }
}

Aggregation response after global filtering

{
    "devices": 1,
    "fieldAggregation": {
        "count": 2,
        "devices": 1,
        "buckets": [
            {
                "key": "val1",
                "count": 1,
                "devices": 1
            },
            {
                "key": "val2",
                "count": 1,
                "devices": 1
            }
        ]
    }
}

The device is selected because one of its properties matches the filter, but all of them appear in the aggregation response. The count values account for both device’s properties. In order to keep only the matching properties in the response, the filter must be moved at nested components level.

Nested level filter on property key

{
    "groupBy": {
        "properties": {
            "field": "value",
            "filter": {
                "key": "prop1"
            }
        }
    }
}

Aggregation response after nested filtering

{
    "devices": 1,
    "fieldAggregation": {
        "count": 1,
        "devices": 1,
        "buckets": [
            {
                "key": "texttest",
                "count": 1,
                "devices": 1
            }
        ]
    }
}

Nested level filter on property value

{
    "groupBy": {
        "properties": {
            "field": "key",
            "filter": {
                "value": "val1"
            }
        }
    }
}

Aggregation response after nested filtering

{
    "devices": 10639,
    "fieldAggregation": {
        "count": 2,
        "devices": 2,
        "buckets": [
            {
                "key": "111",
                "count": 1,
                "devices": 1
            },
            {
                "key": "test",
                "count": 1,
                "devices": 1
            }
        ]
    }
}

The aggregation response contains a single bucket, accounting for the matching property only.

This pattern applies to all nested components. In short, global filtering applies to devices, while nested filtering applies to nested components.

Select all devices with at least a LoRa interface.

Nested level filter on interfaces connectivity

{
    "groupBy": {
        "interfaces": {
            "field": "status",
            "filter": {
                "connector": "lora"
            }
        }
    }
}

Aggregation response after nested filtering

{
    "devices": 10639,
    "fieldAggregation": {
        "count": 264,
        "devices": 259,
        "buckets": [
            {
                "key": "DEACTIVATED",
                "count": 205,
                "devices": 202
            },
            {
                "key": "REGISTERED",
                "count": 34,
                "devices": 34
            },
            {
                "key": "REACTIVATED",
                "count": 22,
                "devices": 20
            },
            {
                "key": "ACTIVATED",
                "count": 2,
                "devices": 2
            },
            {
                "key": "INITIALIZED",
                "count": 1,
                "devices": 1
            }
        ]
    }
}

Select all devices with at least an interface with the requested status.

Nested level filter on interfaces status

{
    "groupBy": {
        "interfaces": {
            "field": "connector",
            "filter": {
                "status": "ONLINE"
            }
        }
    }
}

Aggregation response after nested filtering

{
    "devices": 10639,
    "fieldAggregation": {
        "count": 68,
        "devices": 68,
        "buckets": [
            {
                "key": "sms",
                "count": 57,
                "devices": 57
            },
            {
                "key": "x-connector",
                "count": 9,
                "devices": 9
            },
            {
                "key": "mqtt",
                "count": 2,
                "devices": 2
            }
        ]
    }
}

Select all devices with at least an interface which definition contains the requested profile.

Nested level filter on interfaces definitions

{
    "groupBy": {
        "interfaces": {
            "field": "status",
            "filter": {
               "definition": {
                    "profile": "myProfile"
                }
            }
        }
    }
}

Aggregation response after nested filtering

{
    "devices": 10639,
    "fieldAggregation": {
        "count": 49,
        "devices": 49,
        "buckets": [
            {
                "key": "DEACTIVATED",
                "count": 40,
                "devices": 40
            },
            {
                "key": "REACTIVATED",
                "count": 7,
                "devices": 7
            },
            {
                "key": "REGISTERED",
                "count": 2,
                "devices": 2
            }
        ]
    }
}

Select all devices with a "SILENT" or "UNKNOWN" activity state.

Nested level filter on activity states

{
    "groupBy": {
        "activityStates": {
            "field": "state",
            "filter": {
                "states": ["SILENT", "UNKNOWN"]
            }
        }
    }
}

Aggregation response after nested filtering

{
    "devices": 40,
    "fieldAggregation": {
        "count": 53,
        "devices": 40,
        "buckets": [
            {
                "key": "SILENT",
                "count": 42,
                "devices": 31
            },
           {
                "key": "UNKNOWN",
                "count": 11,
                "devices": 9
            }
        ]
    }
}

Select all devices with an activity state related to the requested activity rule.

Nested level filter on activity states using triggering rule id

{
    "groupBy": {
        "activityStates": {
            "field": "rule.id",
            "filter": {
                "rule": {
                    "id": "myRuleId"
                }
            }
        }
    }
}

Aggregation response after nested filtering

{
    "devices": 40,
    "fieldAggregation": {
        "count": 40,
        "devices": 40,
        "buckets": [
            {
                "key": "myRuleId",
                "count": 40,
                "devices": 40
            }
        ]
    }
}

9.3.8. Geolocation aggregations

A geolocation aggregation is calculated from the values of the devices location fields. The set of response buckets divide space into a number of areas. The cells of this underlying grid are indexed using geoHash codes, which length depend on the requested precision. Precision is expressed as a number in a range of 1 to 12.

Correspondance between precision and effective cells size is approximated below. Note that the cell width reduces moving away from the equator, up to 0 at the poles.

Geohash length Cell width Cell height

1

5000 km

5000 km

2

1250 km

625 km

3

156 km

156 km

4

39.1 km

19.5 km

5

4.9 km

4.9 km

6

1.2 km

0.61 km

7

153 m

153 m

8

38.2 m

19.1 m

9

4.8 m

4.8 m

10

1.2 m

0.596 m

11

14.9 cm

14.9 cm

12

3.7 cm

1.9 cm


Location aggregation

{
    "groupBy": {
      "location": {
          "precision": 3      // optional precision, defaults to 5.
      }
    },
    "options": {
      "includeGeoBoundsInBuckets": true
    }
}

Result

{
    "devices": 10,
    "geoAggregation": {
        "count": 10,
        "devices": 10,
        "buckets": [
            {
                "geoKey": {                       // weighted mean position of devices in this bucket
                    "lat": 48.85418222285807,
                    "lon": 2.346379179507494
                },
                "geoBounds": {                   // coordinates of the smallest enclosing window for all devices of the bucket
                    "topLeft": {
                        "lat": 48.85418226476759,
                        "lon": 2.3463791574827945
                    },
                    "bottomRight": {
                        "lat": 48.85418221085362,
                        "lon": 2.3463792633265257
                    }
                },
                "devices": 8
            },
            {
                "geoKey": {
                    "lat": 44.840204967185855,
                    "lon": -0.560115147382021
                },
                "geoBounds": {
                    "topLeft": {
                        "lat": 44.840204967185855,
                        "lon": -0.560115147382021
                    },
                    "bottomRight": {
                        "lat": 44.840204967185855,
                        "lon": -0.560115147382021
                    }
                },
                "devices": 2
            }
        ],
        "geoBounds": {                          // coordinates of the smallest enclosing window for all devices (for all buckets)
            "topLeft": {
                "lat": 48.85418226476759,
                "lon": -0.5601150635629892
            },
            "bottomRight": {
                "lat": 44.840204967185855,
                "lon": 2.3463792633265257
            }
        }
    }
}

The "geoKey" property is the bucket’s key, showing the weighted mean position (centroid) of all devices in the bucket. More over, for each bucket a "geoBounds" property defines a minimal enclosing box for its devices.

Additionally, the response provides a "geoBounds" property that defines a minimal enclosing box for all devices appearing in response buckets.

9.3.9. Query options

9.3.9.1. Total number of buckets

A stats response can contain up to 50 buckets, shown in descending order of the number of devices in the bucket. Thus, if there are more than 50 buckets, the response contains only the ones that have the most devices. In this case, a client can request a count of the total number of buckets, by setting the "includeTotalKeys" option.

Field aggregation on tags

{
    "groupBy": {
        "field": "tags"
    },
    "options": {
        "includeTotalKeys": true
    }
}

The result contains an additional information showing the total number of bucket keys, including the ones that did not make it to the response.

Result

{
    "devices": 1000,
    "fieldAggregation": {
        "count": 1000,
        "devices": 1000,
        "buckets": [
          ...               // contains the first 50 buckets
        ],
        "keys": 120         // Total number of bucket keys (distinct tag values)
    }
}
9.3.9.2. Missing devices

When a device has no value related to the requested aggregation key, it does not appear in any bucket of the response. In order to track the number of all missing devices, an "includeMissingDevicesCount" option is available.

Field aggregation on tags

{
    "groupBy": {
        "field": "tags"
    },
    "options": {
        "includeMissingDevicesCount": true
    }
}

Result

{
    "devices": 6,
    "fieldAggregation": {
        "count": 6,
        "devices": 6,
        "buckets": [
            {
                "key": "spain",
                "count": 5,
                "devices": 5
            }
        ],
        "missing": 1            // 1 device without any tag
    }
}

Among the 6 devices in the fleet, 5 hold the same tag, while a single one has no tag at all.

In nested components, the missing field does not count devices with no nested component (properties, interfaces or activityStates) as they are filtered out. It only counts devices that hold the requested nested component without the requested aggregation key, as shown in the example below.

Field aggregation on interface profiles

{
    "groupBy": {
        "interfaces": {
            "definition": {
                "field": "profile"
            }
        }
    },
    "options": {
        "includeMissingDevicesCount": true
    }
}

Result

{
    "devices": 10,
    "fieldAggregation": {
        "count": 8,
        "devices": 6,
        "buckets": [
            {
                "key": "Generic_classA_RX2SF12",
                "count": 4,
                "devices": 4
            }
        ],
        "missing": 2
    }
}

There are 10 devices in the fleet, and 6 of them have at least one interface, for a total of 8 interfaces. Among them, 4 interfaces have the same profile, meaning they are LoRa interfaces, and 2 devices have no profile at all, meaning they are not LoRa interfaces.

Apart from interfaces profiles, all other supported nested aggregation keys are mandatory, so the missing value is always 0.

9.3.9.3. Include GeoBounds in buckets

For a location based aggregation:

Location aggregation

{
    "groupBy": {
      "location": {
          "precision": 3
      }
    },
    "options": {
      "includeGeoBoundsInBuckets": true
    }
}

each result bucket will include weighted mean position of devices in this bucket (under geoKey).

Bucket centroid is always returned

       "geoKey": { // weighted mean position of devices in this bucket
           "lat": 48.85418222285807,
           "lon": 2.346379179507494
       },

If includeGeoBoundsInBuckets option is set to true, then location based aggregation result buckets will include coordinates of the smallest enclosing window for all devices of the bucket (under geoBounds).

Bucket GeoBounds is returned when "includeGeoBoundsInBuckets"

        "geoBounds": { // coordinates of the smallest enclosing window for all devices of the bucket
            "topLeft": {
                "lat": 48.85418226476759,
                "lon": -0.5601150635629892
            },
            "bottomRight": {
                "lat": 44.840204967185855,
                "lon": 2.3463792633265257
            }
        }

9.4.1. REST Endpoint

POST /api/v1/deviceMgt/explorer/search

9.4.2. Filter queries

The queries are entirely detailed in common filters.

The format of a search query matches the following pattern:

{
    "query": "...",
    "filters": {...},
    "sort": [...],
    "bookmark": [...],
    "size": ...
}

The global request uses the following description :

JSON Params Description

query

Optional. partial search allows to find devices by indicating partial values. It is searched among the following fields: id, name, group.path, tags, properties.key, properties.value. It is a string format, case-insensitive and if there are multiple words they are filtered with the OR operator. At least 3 characters are needed to find words of more than 3 characters. Smaller words can be found by indicating their complete value. 256 characters maximum

filters

Optional. identical criteria described in common filtering chapter

size

Optional. maximum number of devices to return

sort

Optional. array of sort elements which accepts "group.path", "name", "interfaces.status", "interfaces.enabled", "interfaces.lastContact", "created", "updated", "relevance", "id". "id" must be set at the end. Per default, when array is empty or the "id" is not set, the sort will be done by ascending "id". More over to indicate a sort on reverse way, a "-" must be set in front of element (Ex: "-id").

bookmark

Optional. array of indexes of the last research (compatible with the sort list in number and order). When it is using, the bookmark corresponding to the "id" must always be set (even if not set in the sort list or sort list is empty).

If "query" and "filters" fields are present, they are processed with AND operator. "bookmark" is used to optimize the search when consecutive requests are made one after the other, in executing the search from the last found device.

According to the internal model, a typical response would look like this:

{
    "bookmark": [
            "/grp1",
            "ONLINE",
            true,
            "2019-08-20T15:05:58.047Z",
            "urn:lo:nsid:myNs:myId"
    ],
    "devices": [
      {
         "id": "urn:lo:nsid:sensor:temp001",
         "name": "mySensor001",
         "description": <<some description>>,
         "activities": [
            {
             "ruleId": "e26309b1-3bb1-4ac6-929b-50d364188c7e",
             "state": "SILENT"
            }
         ],
         "aggregatedActivityState": "SILENT",
         "tags": ["Lyon", "Test"],
         "properties" : {
             <<key>>: <<value>>
         },
         "group": {
             "id": <<id>>,
             "path": <<myPathId>>
         },
         "interfaces": [
               {
                 "connector": <<myConnector>>,
                 "nodeId": <<interface Id>>,
                 "enabled": <<true/false>>,
                 "status": <<the status of the interface>>,
                 "lastContact": <<date>>,
                 "definition": {
                       ........to learn more, see the "Device interface representation" section
                 },
                 "activity": {},
                 "capabilities": {
                       "command": {
                          "version" : <<versionNumber>>,
                          "available": <<true/false>>
                       },
                       "configuration": {
                          "available": <<true/false>>
                       },
                       "resources": {
                          "available": <<true/false>>
                      }
                  }
               }
           ],
           "created": <<date>>,
           "updated": <<date>>,
           "location": {
               "lat": <<Latitude value>>,
               "lon": <<Longitude value>>,
               "alt": <<Altitude value>>,
               "accuracy":<<accuracy value>>,
               "provider":<<provider value>>,
               "lastUpdate": <<date>>
            }
       }
    ]
}

The response contains lists of :

  • bookmarks : representing the indexes of the last research. These indexes follow the elements set in the sort in number and order. For example, if sort=["created","id"] then bookmark will return [<last index of created>, <last index of id>]

  • inventory devices with the following model description :

JSON Params Description

id

device unique identifier (Cf. device identifier)

description

Optional. detailed description of the device

name

Optional. name of the device

tags

Optional. list of additional information used to tag device messages

properties

Optional. map of key/value string pairs detailing device properties

group

group to which the device belongs. The group is defined by its id and its path

interfaces

Optional. list of device network interfaces (Cf. interface object model)

created

creation date of the device

updated

last update date of the device

activities

Optional. device activities with state of its activity rule

aggregatedActivityState

Optional. device aggregated activity state of 'activities' field (Cf. aggregated activity state)

location

Optional. the last location of device location returned by data after data message enrichment process.

And for each interface the model is :

JSON Params Description

connector

connector identifier

nodeId

interface unique identifier

enabled

define if the interface is enabled or disabled

status

interface status

definition

interface definition. The definition depends on connector.

lastContact

Optional. last contact date of the connectivity

activity

interface activity. The activity depends on connector.

capabilities

interface capabilities.

created

registration date of the interface

updated

last update date of the interface

For more information on each connector definition, activity and status, see the appropriate section:

10. Cellular Networks (Beta)

10.1. Principle

Cellular network management APIs allows user to retrieve connectivity information from Orange connectivity management provider. Once the customer account is configured information such as last network attachment, locations, session history, etc. can be retreived. Retrieved information can vary depending on your provider, region and offer package account.

As of today, the only provider available is Orange Malima for the following regions :

Provider Available region

Malima

France, Spain, Poland, Romania, Slovakia

10.2. Subscriptions

A subscription is a network subscription identified by a subscriptionId. A subscription is linked to a SIM card and contains information such as :

  • The last network interaction

  • Attached device

  • Provider account subscription’s

  • SIM card capabilities and ids

10.2.1. Search cellular networks subscriptions (Beta)

10.2.1.1. Request

Endpoint:

POST /api/v1/networks/cellular/subscriptions/search

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Body:

JSON Params Description

type

Search type of the subscription, allowed types : "msisdn" or "imei"

value

Search value of the subscription (max 15 characters)

Example:

POST /api/v1/networks/cellular/subscriptions/search
{
    "type" : "msisdn",
    "value" : "337000003543020"
}
10.2.1.2. Response

HTTP Code:

200 OK

Body:

[
    {
        "id": "06361404",
        "msisdn": "337000003543020",
        "imsi": "208017401123509",
        "sim": {
            "status": "ACTIVATED",
            "iccid": "89330129210007850940",
            "serialNumber": "2921000785092",
            "lastUpdate": "2021-02-03T09:45:35Z"
        },
        "device": {
            "imei": "352753093029773",
            "lastUpdate": "2021-02-03T09:45:35Z"
        },
        "provider": {
            "type": "malima",
            "configuration": {
                "cen": "mycen",
                "instanceId": "myInstanceId"
            },
            "link": "https://m2mexpress.fr.orange-business.com/mac/customer/fleet/details.do?subId=06361404&category=SIM"
        }
    }
]
JSON Params Description

id

subscription unique identifier

msisdn

Number uniquely identifying a subscription in a Global System for Mobile communications

imsi

International Mobile Subscriber Identity

sim

Sim of the subscription (Cf. Sim format)

device

Device of the subscription (Cf. Device format)

provider

Provider of the subscription (Cf. Provider format)

Error case:_

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

403

FORBIDDEN

Forbidden request

404

CELLULAR_SUBSCRIPTION_NOT_FOUND

Subscription not found

10.2.2. Get cellular networks subscription (Beta)

10.2.2.1. Request

Endpoint:

GET /api/v1/networks/cellular/subscriptions/{subscriptionId}

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Example:

GET /api/v1/networks/cellular/subscriptions/06361407
10.2.2.2. Response

HTTP Code:

200 OK

Body:

{
    "id": "06361404",
    "msisdn": "337000003543020",
    "imsi": "208017401123509",
    "sim": {
        "status": "ACTIVATED",
        "iccid": "89330129210007850940",
        "serialNumber": "2921000785092",
        "lastUpdate": "2021-02-03T09:45:35Z",
        "capabilities" : {
             "smartSim" : true
        }
    },
    "device": {
        "imei": "352753093029773",
        "lastUpdate": "2021-02-03T09:45:35Z"
    },
    "provider": {
        "type": "malima",
        "configuration": {
            "cen": "mycen",
            "instanceId": "myInstanceId"
        },
        "link": "https://m2mexpress.fr.orange-business.com/mac/customer/fleet/details.do?subId=06361404&category=SIM"
    },
    "network": {
        "status": "ONLINE",
        "radio": "4G",
        "lastUpdate": "2020-10-28T16:13:04Z",
        "mobileCountry": {
            "code": "208",
            "value": "France"
        },
        "mobileNetwork": {
            "code": "208-01",
            "value": "Orange"
        },
        "lastNetworkInteraction": "DATA"
    }
}
JSON Params Description

id

subscription unique identifier

msisdn

Number uniquely identifying a subscription in a Global System for Mobile communications

imsi

International Mobile Subscriber Identity

sim

Sim of the subscription (Cf. Sim format)

device

Device of the subscription (Cf. Device format)

provider

Provider of the subscription (Cf. Provider format)

network

Network of the subscription (Cf. Network format)


The format of the sim is the following:

JSON Params Description

status

Status of SIM : PRE_ACTIVATED, ACTIVATED, SUSPENDED, CANCELLED …​

iccid

Integrated Circuit Card Identifier

serialNumber

Serial Number of SIM

lastUpdate

Last update date of SIM

capabilities

SIM capabilities (Cf. Sim capabilities format)


The format of the sim capabilities is the following:

JSON Params Description

smartSim

true when SIM supervision localization is available


The format of the device is the following:

JSON Params Description

imei

International Mobile Equipment Identity

lastUpdate

Last update date of device


The format of the provider is the following:

JSON Params Description

type

Provider type. Allowed values: [malima]

configuration

Provider customer account configuration

link

link to access portal M2M


The format of the network is the following:

JSON Params Description

status

Status of the last network attachment: ONLINE or OFFLINE

radio

Radio type of network attachment: 2G, 3G, 4G, 5G or UNKNOWN

lastUpdate

Last update date of network attachment

mobileCountry

Mobile country (if any)

mobileNetwork

Mobile network (if any)

lastNetworkInteraction

Last interaction of network attachment: DATA or SMS

Error case:_

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

403

FORBIDDEN

Forbidden request

404

CELLULAR_SUBSCRIPTION_NOT_FOUND

Subscription not found

10.3. Location

Last known location of the associated device can be retrieve. This location can be provided by network probes (only available for France) or with SmartSim location service (available for some regions).

Only available for some regions and depends on your network provider option package.

10.3.1. Get cellular networks location (Beta)

10.3.1.1. Request

Endpoint:

GET /api/v1/networks/cellular/subscriptions/{subscriptionId}/location

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Example:

GET /api/v1/networks/cellular/subscriptions/06361407/location
10.3.1.2. Response

HTTP Code:

200 OK

Body:

{
    "lat": "44.8",
    "lon": "3.7",
    "accuracy": "120.0",
    "provider": "network",
    "lastUpdateTs": "2020-10-28T16:13:04Z",
    "link": "https://m2mexpress.fr.orange-business.com/mac/customer/fleet/deviceinfo/localization-details.do?subId=06361407"
}
JSON Params Description

lat

coordinate latitude

lon

coordinate longitude

accuracy

position accuracy in m

lastUpdateTs

date of the position

provider

provider of the location ("network" when supplied by network probes (only available for France) or "smart-sim" when supplied by SmartSim location service)

link

link to access the location tab on the service provider portal

Error case:_

HTTP Code Error code message

400

GENERIC_INVALID_PARAMETER_ERROR

The submitted parameter is invalid.

403

FORBIDDEN

Forbidden request

404

CELLULAR_SUBSCRIPTION_NOT_FOUND

Subscription not found

10.4. Traffic history

Provide an aggregated view of the session history of the subscription. Max history depth is 30 days.

10.4.1. Get cellular subscription traffic history (Beta)

The server will collect data from cellular network providers asynchronously and store them into a cache.

On first GET query - or on empty/outdated cache- server accept the query(202) and then collect data from providers.

GET query must be repeated by the client until data are ready and returned from the cache (200).

There is a way to ignore an existing cache by using forceRefresh parameter.

10.4.1.1. Request

Endpoint:

GET /api/v1/networks/cellular/subscriptions/{subscriptionId}/traffic/history

HTTP Headers:

X-API-Key: <your API key>
Content-Type: application/json
Accept: application/json

Parameters:

HTTP Params Description

limit

(optional) limit the response to the last n elements in the "data" object. 1000> n> 0

interval

(optional) requested aggregation format, "1h"(one hour), "1d"(one day) or "1w"(one week).

forceRefresh

(optional) force the refresh of data: "true" (don’t use cache) or "false" (use cache when available).

timeZone

(optional) time zone for daily or weekly aggregation, with TZ database name ("UTC", "Europe/Paris") or UTC Offset ("-02:00", "%2B04:00").

Example:

GET /api/v1/networks/cellular/subscriptions/06361407/location?limit=1&interval=1h&timeZone=Europe/Paris
10.4.1.2. Response (accepted)

HTTP Code:

202 ACCEPTED

(empty payload)

10.4.1.3. Response (with data)

HTTP Code:

200 OK

Body:

{
  "data": [
    {
      "dataIn": 1096,
      "dataOut": 1096,
      "smsIn": 5,
      "smsOut": 5,
      "timestamp": "2021-02-03T09:00:00+01:00"
    }
  ],
  "timestamp": "2021-02-03T10:45:35+01:00"
}
JSON Params Description