Message routing

This chapter explains how you can route data messages or device oriented events to an external system, via Live Objects FIFO queues or httpPush (webhooks).

In order to route your messages, you must provision an action policy:

  • which messages you want to route (triggers)

  • how you want to route your messages (actions)

Routable types summary

When devices publish messages that require routing to business applications. These messages can be device events, data detection or network events, message routing is applied. Messages can be consumed via Application mode (MQTT over FIFO topics), HTTP push (webhooks), and the Listen REST API (when applicable).. To help their dispatching and use, the messages are labeled (by type) and versioned.

This section provides a global overview of supported routed event types, please refer to specific section for detailed output data model.

Description Public type Available version number Available filters in triggers & actions feature

Data message

dataMessage

1

connectors, groupPaths, deviceIds, tags

Matching fired event

matchingFired

1

ruleIds

State change event

stateChange

1

ruleIds

Device activity event

deviceActivity

1

ruleIds, deviceIds

Device created event

deviceCreated

1

connectors, groupPaths, tags

Device deleted event

deviceDeleted

1

connectors, groupPaths, tags

Device status event

deviceStatus

1

connectors, groupPaths

Command status event

commandStatus

1

status

LoRa® network event

loraNetwork

1

messageTypes

LoRa® gateway status event

loraGatewayStatus

1

 — 

Connectivity management platform event

connectivityManagementPlatformEvent

1

eventPayloadTypes

Alarm event

alarmEvent

1

alarmRule.type

At the moment, only version 1 is available. If new versions are added to the versioning space, the support team will notify you of the change.

About action policies, triggers and actions

To route messages and events, you define an action policy that links: - one trigger (what to route, with optional filters), and - one or more actions (how/where to deliver: FIFO publish, HTTP push, etc.).

Data Messages vs Events: what gets routed

Data Messages and Events are both “routed messages” (they have a public type and a version), but they do not come from the same source and they don’t carry the same kind of information.

  • Data Messages (type=dataMessage)

  • Emitted by: devices (or a business app posing as a device) via MQTT, LwM2M, LoRa, REST ingestion.

  • Purpose: transport business payloads from the device (measurements, states) in the value field.

  • Nature: “raw” device data enriched by Live Objects (metadata, tags, extra, location…).

  • Routing: you select them with a dataMessage trigger and filters like connectors, groupPaths, deviceIds, tags.

  • Events (types: matchingFired, stateChange, deviceActivity, deviceCreated, deviceDeleted, deviceStatus, loraNetwork, loraGatewayStatus, connectivityManagementPlatformEvent)

  • Emitted by: the platform (services like SEP/SP/AP/Device Management), the network (LoRa), or an external platform (e.g., CMP). Not by the device itself.

  • Purpose: signal a change, a detection or a lifecycle/status transition. These are notifications, distinct from the device’s business payload.

  • Routing: you select them with the corresponding event trigger and its specific filters (e.g., ruleIds, status, messageTypes, eventPayloadTypes, connectors/groupPaths for some DM events).

Filtering at a glance

Routed type Emitted by Typical filters What you receive

dataMessage

Device / Business app

connectors, groupPaths, deviceIds, tags

The original device payload under value plus Live Objects metadata

matchingFired, stateChange, deviceActivity

Platform (detection/processing services)

ruleIds (and sometimes deviceIds for activity)

An event describing the detected condition or state transition

deviceCreated, deviceDeleted, deviceStatus

Platform (Device Management)

connectors, groupPaths (status only)

A device lifecycle/status notification

loraNetwork, loraGatewayStatus

Network (LoRa)

messageTypes (loraNetwork)

A network‑level notification (e.g., UNCONFIRMED_DATA_UP, JOIN_REQUEST…)

connectivityManagementPlatformEvent

External platform (CMP)

eventPayloadTypes

A CMP notification (e.g., prepaid_bucket)

How routing ties them together

  1. Devices publish Data Messages; Live Objects enriches them (type=dataMessage when routed).

  2. The platform may independently emit Events (not sent by devices) when rules or state machines fire, when device lifecycle changes, or when the network/external platforms notify something.

  3. Your Action policy picks what to deliver:

    • Use a dataMessage trigger to route device data.

    • Use an event trigger (matchingFired, stateChange, deviceStatus, loraNetwork, …) to route notifications.

  4. Filters use:

    • OR logic inside a list (e.g., connectors: ["mqtt","lora"]).

    • AND logic across different lists (e.g., connectors AND groupPaths).

Routing overview (schematic)

routing-overview

Action policy

The relationship between a trigger and multiple actions is called an action policy. The action policy must be provisioned in Live Objects with the HTTP API or using the web portal. Once the action policy is provisioned and enabled (field enabled set to true), your messages will be routed using the chosen action mode (FIFO queue or HTTP push).

Prior to provisioning your rule with an http push action, please make sure your web server is up-and-running.

  • you have created your FIFO in Live Objects if you want to use a FIFO queue

  • your web server is up and running if you want to use an HTTP push action

Only new routed messages/events are delivered once the action policy is provisioned. Existing data messages already stored in Live Objects are not re-routed.

An action policy is composed of 2 main sections:

  • triggers: define what you want to route. Usually, one trigger is defined in one action policy, except for device provisioning events, where you can define a trigger for deviceCreated events, and a trigger for deviceDeleted events, in the same action policy.

  • actions: define how you want to route these messages/events.

The action policy API is detailed in Swagger.

Provisioning

To create a new action policy:

Endpoint:

POST /api/v1/event2action/actionPolicies
An action policy for message routing has the following top level data representation:
{
  "name": "some_user_defined_policy_name",
  "enabled": true,
  "triggers": {
    "dataMessage": {
      "version": 1,
      "filter": {
        "connectors": [
          "lora"
        ],
        "groupPaths": [
          {
            "includeSubPath": false,
            "path": "/europe/france"
          }
        ],
        "tags": [
          ["HIGH","ALERT"],
          ["PROD"]
        ]
      }
    }
  },
  "actions": {
    "fifoPublish": [
      {
        "fifoName": "myFifo"
      }
    ]
  }
}

The policy id is automatically created by Live Objects and will be returned in the POST response body.

field name is required description

name

optional

Defines a user-friendly name for the action policy

enabled

required

Enable or disable the action policy

suspension

optional

In case of abnormal activity on this rule, it can be suspended (enabled will be set to false). Read-only: this field is handled by the platform. Once the problem is corrected, use the PUT API with enabled=true to resume the rule.

triggers

required

Defines the type of trigger that will start an action.

Filtering section: criteria in a filter are combined with an AND boolean logic. The OR operator is applied between the items inside each filter list. The filters depend on the trigger type.

Note: the triggers object should have exactly one trigger defined in most cases (except for deviceCreated & deviceDeleted).

dataMessage

optional

Available filters for data message:
  • connectors: a list of interfaces to be monitored ("http", "mqtt", "lora", "sms", "x-connector")

  • deviceIds: a list of device identifiers (as String)

  • groupPaths: a list of device group paths

  • tags: a list of lists of tags.

deviceStatus

optional

The device status can be one of the following: "ONLINE", "OFFLINE", "REGISTERED", "DELETED", "ACTIVATED"…​ See all the device status in this chapter.

Available filters for the device status events:
  • connectors: a list of interfaces to be monitored ("http", "mqtt", "lora", "sms", "x-connector")

  • groupPaths: a list of device group paths

deviceCreated

optional

Available filters for the device created events:
  • connectors: a list of interfaces to be monitored ("http", "mqtt", "lora", "sms", "x-connector")

  • groupPaths: a list of device group paths

  • tags: a list of lists of tags

deviceDeleted

optional

Available filters for the device deleted events:
  • connectors: a list of interfaces to be monitored ("http", "mqtt", "lora", "sms", "x-connector")

  • groupPaths: a list of device group paths

  • tags: a list of lists of tags

commandStatus

optional

Available filters for the command status events:
  • status: a list of command status to be monitored ("pending", "processed"…​) See more details in the device management chapter.

loraNetwork

optional

Available filter for the network info events from LoRa® devices:
  • messageTypes: a list of LoRa® network info events within six available message types:

    • "UNCONFIRMED_DATA_UP"

    • "CONFIRMED_DATA_UP"

    • "UNCONFIRMED_DATA_DOWN"

    • "CONFIRMED_DATA_DOWN"

    • "JOIN_REQUEST"

    • "JOIN_ACCEPT"

loraGatewayStatus

optional

Sent event when a LoRa® gateway status changes. Status can be "ONLINE", "OFFLINE" or "UNKNOWN".

connectivityManagementPlatformEvent

optional

Event sent by your cellular connectivity management platform (e.g. Orange CMP 'Portail M2M' / 'Conecta IoT' / 'Simply IoT' platform).

alarmEvent

optional

Available filter for alarm events: alarmRule.type with supported values messageDeliverySuccessRatio (event sent when a message delivery success ratio alarm is triggered for account metrics monitoring) and actionSuspended (event sent when an action is suspended due to high error rate). Supported alarms full description is available in account alarming chapter.

actions

required

Defines the type of action:

emails

optional

A collection of Email actions (see Email notification section)

sms

optional

A collection of SMS actions (see SMS notification section)

fifoPublish

optional

A collection of FIFO names where the event message will be published (see FIFO notification section)

httpPush

optional

A collection of HTTP push actions (see HTTP push action section)

azureEventHubs

optional

A collection of Azure Event Hubs actions (see Azure Event Hubs notification section)

To retrieve your action policy:

Endpoint:

GET /api/v1/event2action/actionPolicies/{policyId}

Examples

An example of an action policy with triggering on a new data message for a specific device. The output message is routed to a specific FIFO.
{
    "id": "202ada2a-e267-4427-9d7f-2756c2a2b1dd",
    "name": "push data fifo",
    "enabled": true,
    "triggers": {
        "dataMessage": {
            "version": 1,
            "filter": {
                "deviceIds": ["<your_device_id>"]
            }
        }
    },
    "actions": {
        "emails": [],
        "sms": [],
        "httpPush": [],
        "fifoPublish": [
            {"fifoName": "<your fifo name>"}
        ]
    }
}
The same example of an action policy with triggering on a new data message for a specific device. the output message is pushed to a website using HTTP Push action.
{
    "id": "202ada2a-e267-4427-9d7f-2756c2a2b1de",
    "name": "Push data message with a webhook",
    "enabled": true,
    "triggers": {
        "dataMessage": {
            "version": 1,
            "filter": {
                "deviceIds": ["<your_device_id>"]
            }
        }
    },
    "actions": {
    "emails": [],
    "sms": [],
    "httpPush": [
    {
        "webhookUrl": "https://webhook.site/....",
        "headers": {
          "authorization": [
            "Bearer 00000000-0000-0000-0000-000000000000"
          ]
        },
        "content": "<text>+<mustache template>",
        "retryOnFailure": true
      }
    ],
    "fifoPublish": []
  }
}

Now that you know how to create an action policy, you can find the format of all public data messages and events in this chapter.

Triggers

You probably want to route only a subset of your messages. In order to choose which messages to route, the triggers section must be set in the action policy. Triggers enable downstream action execution, passing the event or the message to the specified actions.

Format

Example of a trigger for data message routing
 "triggers": {
    "dataMessage": {                    (1)
      "version": 1,                     (2)
      "filter": {                       (3)
        "connectors": [ "mqtt","sms"],
        "groupPaths": [{
            "includeSubPath": false,
            "path": "/europe/france"
          }]
      }
    }
  }
1 the type of message to be routed : data message, deviceStatus, commandStatus message
2 expected public data message output version
3 filter definition: criteria to choose which messages will be routed
more info on public data message format

Message filtering

Message filtering will select the messages and apply all filters with a "AND" logic operators: groupPaths, connectors, deviceIds, tags. Filters lists are limited to 20 items.

In the previous example, the message will be selected if it has been emitted through the "mqtt" OR "sms" connector, AND belonging to "/europe/france" group.

Filter Available for Description

filter.groupPaths

dataMessage, deviceStatus, deviceCreated, deviceDeleted

Filter the messages based on the group of the device that posted it. The message will pass through the filter when at least one group matches ("OR" logic).

filter.connectors

dataMessage, deviceStatus, deviceCreated, deviceDeleted

Filter the messages based on the network connector ("http", "lora", "mqtt", "sms", "x-connector") used to post it. The message will pass through the filter when at least one connector element matches ("OR" logic).

filter.deviceIds

dataMessage, deviceActivity

Filter the messages based on the deviceId of the device that posted it ('metadata.source' field). The message will pass through the filter when at least one deviceId matches ("OR" logic).

filter.tags

dataMessage, deviceCreated, deviceDeleted

Filter the messages based on its 'tags' field. The message will pass through the filter when all of the tags in at least one of the set of tags matches. For instance :

  • [["HIGH", "ALERT"],["PROD"]] will match any message containing 'PROD' tag;

  • and also any message containing both 'HIGH' and 'ALERT' tags.

filter.status

commandStatus

List of command status : PENDING, PROCESSING, PROCESSED, CANCELED, ERROR, RETRYING, EXPIRED.

filter.ruleId

stateChange, deviceActvity, matchingFired

List of rule ids to filter.

filter.messageTypes

loraNetwork

List of message types: "UNCONFIRMED_DATA_UP", "CONFIRMED_DATA_UP", "UNCONFIRMED_DATA_DOWN", "CONFIRMED_DATA_DOWN", "JOIN_REQUEST", "JOIN_ACCEPT"

filter.eventPayloadTypes

connectivityManagementPlatformEvent

List of the connectivity management platform event types to filter. The message will pass through the filter when at least one event payload type match ("OR" logic). Empty list means all messages will be routed. The event type values depend on your cellular connectivity management platform. For instance, for Orange CMP platform, you can filter on "prepaid_bucket" event type.

filter.alarmRule.type

alarmEvent

List of alarm rule types to filter. Supported values are messageDeliverySuccessRatio (event sent when a message delivery success ratio alarm is triggered for account metrics monitoring) and actionSuspended (event sent when an action is suspended due to high error rate).Supported alarms full description is available in account alarming chapter.

Actions

FIFO publish action

The purpose of this action is to publish to a Live Objects FIFO when a trigger is activated. FIFO publish is a routing feature without mustache templating (i.e. the entire data message or event is published in the FIFO, you can’t template it).

The API to manage FIFO is detailed in swagger.

Representation of a FIFO action
{
    "fifoName": "destinationfifo",
    "noRetention": false
}
Field Description

fifoName

Name of the FIFO that will receive the triggered message

noRetention

If true, messages published to the FIFO from this action will not be stored; they will be immediately dropped if no subscriber is consuming from the FIFO at the time the messages are published.

Example of an action policy routing all new data messages to a FIFO
{
    "name": "push data new to fifo",
    "enabled": true,
    "triggers": {
        "dataMessage": {
        "version": 1
    }
  },
    "actions": {
        "fifoPublish": [{"fifoName":"mydata"}]
    }
}
Example of an action policy sending data messages of a specific device to a FIFO without storing messages that are not consumed immediately
{
    "name": "push data new to fifo",
    "enabled": true,
    "triggers": {
        "dataMessage": {
            "version": 1,
            "filter": {
                "deviceIds": ["urn:lo:nsid:mqtt:deviceId2"]
            }
        }
    },
    "actions": {
        "fifoPublish": [{
                "fifoName": "mydata",
                "noRetention": true
            }]
    }
}

Creating a FIFO publish action will automatically create the corresponding FIFO if it does not already exist. The total number of FIFO is limited depending on your offer so you may need to remove existing action policy with FIFO publish action to create new ones.

By default, a FIFO will store messages for a few days depending on your offer. If no subscriber consumes the messages during this period, they will be dropped. However, storing messages coming from an action policy can be disabled by setting the noRetention field to true. In this case, if no subscriber is consuming from the FIFO at the time messages are published, these messages will be immediately dropped.

If the FIFO messages published from an action are not consumed for 7 consecutive days, or if the targeted FIFO has been deleted; the ActionPolicy will be disabled. Its suspension field will provide additional details.

Http Push action

The purpose of this action is to do an HTTP POST to a given URL with custom headers and a custom body. The body can be templated using the Mustache templating syntax.

Depending on the user needs, a retry policy can be enabled to be more resilient to listening endpoint downtimes.

Representation of a Http Push action
{
     "webhookUrl": String,
     "headers": Map of <String,List of String> ({"key": ["value1","value2",...]}),
     "retryOnFailure": boolean,
     "jsonPath": String,
     "content": String
}
field name is required description

webhookUrl

required

defines the location of the webhook (only the secured ports 443, 8443 and 9243 are allowed, the insecure ports ex: 80 or 8080 are not supported).

headers

optional

defines custom headers that are sent along the HTTP POST request.
This can be used to pass authorization headers or any header required to connect to an endpoint.

signingSecret

optional

Secret used to compute an HMAC signature of the HTTP POST request. The signature is added as a header for authenticity and integrity validation.
The signature header name is x-orange-hmac-sha256-signature and it is accompanied by a timestamp header named x-orange-timestamp-epoch-seconds. SigningSecret is a UTF-8 string with a length between 20 and 128 characters. See HTTP Push signature verification process.

retryOnFailure

optional

Enables retry on failure policy (see related section)

jsonPath

optional

Select a part of the triggering data using a jsonPath syntax. This selected data will be used as the root of the template datacontext. This field can be omitted when you want to work with the whole data in template.

content

optional

A string representing a Mustache template. This template will be rendered as the request body.

Example of Http Push action on a data message trigger
{
    "name": "some_user_friendly_name",
    "enabled": true,
    "triggers": {
        "dataMessage": {
        }
    },
    "actions": {
        "httpPush": [{
            "webhookUrl": "https://hooks.myservice.com/services/SOMEWEBHOOKREFERENCE",
            "headers": {"authorization": ["Bearer 00000000-0000-0000-0000-000000000000"]},
            "retryOnFailure": true,
            "content": "{\"text\": \"data pushed to stream : {{streamId}}, at {{timestamp}}\"}"
        }]
    }
}

Generated headers

x-orange-lo-policy-id

Every Http Push request contains a header with the action policy id.

If the id of an action policy is 6c95837b-251d-41d8-95f1-42facdf8e71e. The http push will have the following header:

x-orange-lo-policy-id:6c95837b-251d-41d8-95f1-42facdf8e71e
x-orange-lo-message-id

Every Http Push request contains a header with an id that identifies that push uniquely (this id will be kept across retries in case of errors). This id can be used to identify if a message has been delivered multiple times to the webhook.

x-orange-lo-message-id: 00000000-0000-0000-0000-000000000000
x-orange-timestamp-epoch-seconds

If a signingSecret is configured, this header is added with the Unix epoch timestamp (in seconds). See below for how to use it to validate the request.

x-orange-hmac-sha256-signature

If a signingSecret is configured, this header is added with an HMAC-SHA-256 signature (hex-encoded). See below for how to use it to validate the request.

x-orange-hmac-sha256-signature: 28208ff5566f18c2ae740294cf77fd683000947c64c83156969b5a45dfba4b17

Live Objects will try to validate the body of the HTTP POST as JSON object and will set the request Content-Type header accordingly:

  • application/json if the body contains valid JSON object

  • text/plain otherwise

HTTP Push signature verification process

If a signingSecret is configured, Live Objects signs the HTTP POST message using the secret key (signingSecret) and the HMAC-SHA-256 algorithm, encodes the resulting signature in hex, and includes it in the x-orange-hmac-sha256-signature header. To mitigate replay attacks, Live Objects also adds a x-orange-timestamp-epoch-seconds header.

The webhook server should validate the request by computing the signature and comparing it with the one provided in the headers using the following steps.

  1. Store the signingSecret securely on your server

  2. Gather inputs as UTF-8 strings:

    • originid = x-orange-lo-policy-id header value

    • messageuuid = x-orange-lo-message-id header value

    • epochseconds = x-orange-timestamp-epoch-seconds header value

    • requestbody = exact HTTP POST body as a string (UTF-8)

  3. Check freshness: compare epochseconds with the server’s local time; it should be within an acceptable timeframe (e.g., 3–5 minutes). Using an NTP-synchronized clock is recommended.

  4. Build the input string with colon separators, without extra spaces: epochseconds:originid:messageuuid:requestbody

  5. Compute the HMAC using HMAC-SHA-256 with signingSecret as key, then hex-encode the result.

  6. Compare the computed signature to the x-orange-hmac-sha256-signature header value. Use a constant-time comparison if possible. If they match and the timestamp is within the allowed window, the request is considered authentic and unmodified.

Example

  • epochseconds: 1710000000 (GMT: Saturday 9 March 2024 16:00:00)

  • originid: origin-123

  • messageuuid: uuid-456

  • requestbody: {"foo":"bar"}

  • signingSecret: mySecretKey

String to sign: 1710000000:origin-123:uuid-456:{"foo":"bar"}

Signature (hex): 28208ff5566f18c2ae740294cf77fd683000947c64c83156969b5a45dfba4b17

General documentation regarding webhooks and HMAC:

Policy and error management

When an error message is sent back by the destination resource, a retry policy will occur (if configured when the Http Push Action was created). The Http Push action will be retried depending on the HTTP error code sent back from the destination resource to Live Objects.

Table 1. Error handling according to HTTP ERROR
HTTP ERROR CLASS Error handling mode

4xx

Unrecoverable error: discard Http Push action

5xx

Recoverable error: retry Http Push action execution (if retryPolicy is true) otherwise discard the Http Push action execution

When enabled, the retry policy will try to regularly post a request to the resource referenced by the Http Push action url parameter. These retries will be attempted over around twenty-four hours. The retry pattern is subject to change, but it currently follows:

Table 2. Retries and delays (in order)
# of retry delay between retry

3

5 seconds

3

5 minutes

12

2 hours

In the case where the retries are unsuccessful, the Http Push action execution is discarded.

If the HttpPush error rate is too high (> 90%) for 7 consecutive days; the ActionPolicy will be disabled. Its suspension field will provide additional details.

Message Overflow

If the targeted servers for HTTP Push (webHook) are down or slow, HTTP push requests will be buffered. The buffer size, mutualized between all your HTTP Push action policies can contain up to 10.000 requests. If this limit is reached, the oldest request will be discarded first and an AuditLog will be recorded.

As a consequence, if more than 10.000 messages are waiting to be pushed to your HTTP servers, then some of them will start to be dropped. The messages pending retry are not included in this amount.

There are 2 typical cases where this can happen :

  • the HTTP server is not available, then each message needs to wait for the 5s timeout before continuing its retry cycle

  • the HTTP server has a slower response time than the rate at which messages are being pushed

If this happens, the number of pending messages will increase up to 10.000 and the overflow mechanism will be triggered.

In order to decrease the risk of congestion and overflow, HTTP Push requests are performed with some parallelism when several messages are pending (up to 10 concurrent requests).

Security considerations

A secure resource endpoint (HTTPS) should always be used. Using a non secure endpoint (HTTP) is a security issue as the data exchange between Live Objects and the resource endpoint will not be encrypted. This is especially true when leveraging the custom headers mechanisms to pass authentication token.

As a general recommendation, when using a custom authorization header, consider it insecure and be sure to give the token/credentials the least permissions. It should only be able to do an HTTP POST on the defined resource location.

Http Push Results

Each Http Push action with an ERROR will generate an audit log message. This can help analyze traffic problems.

The solution is to:

{
    "tenantId": "httppush550b5cd6-b8c6-49a4-baa9-d3c21a84202d",
    "httpPushRequest": {
        "url": "http://localhost:14567",
        "retryOnFailure": false,
        "headers": null,
        "requestBody": "{\"x\":0}",
        "messageUUID": "b5540f77-bbc8-42c8-9942-35c0b133a689"
    },
    "success": false,
    "responseStatusCode": 400,
    "responseBody": "KO",
    "errorMessage": "an error message"
}

About HTTPS certificate

When using https to push data to a webhook, the certification chain must be valid according to the default Java 8 JVM implementation. Any self signed certificate or certificate issued by an unknown organization (according to the JAVA 8 JVM) presented by a webhook will be refused and the http push action will not be executed.

About HTTP/HTTPS authorized ports and reachable IP address

  • The list of ports authorized by Live Objects during a http push action, are: 443 and 8443 (HTTPS), 80 and 8080 (HTTP), 9243 for ES. Other ports are blocked.

  • The Remote HTTP Servers or domains with IPV6 IP address are not supported by Live Objects.

If you have a 403 forbidden error, you need to check if you have using a right port number. In the other hand, the remote server must allow the port number that you are using.

HTTP_PUSH vs FIFO

Performance Security Resilience Easy to integrate Keep message sequence Recommended for

HTTP PUSH

➖ : significant protocol overhead (http headers, 200 OK responses)

➖ : retries increases the load

➖ : requires to open and secure a TCP port on the Internet to receive traffic.

➖ : buffer of 10K messages max / account, 24h of retry max

➕ : http very well known in the developers community

➕ : compatible with stateless servers

➖ : Retry policy changes significantly the sequencing of messages.

➖ : Complicates the processing of events in the customer’s IT (typically state processing)

prototypes and small applications with low quality of service constraints

MQTTs Application

➕ : messages are acked or stay in the FIFO, no need of retries

➕ : optimized protocol overhead

➕➕ : no incoming connections from the Internet to your server, only outgoing, strong authentication supported on Live Objects (TLS client certificate)

➕ : buffer (FIFO queue) for up to 7 days of message retention in the FIFOs

➖ : requires the integration of a mqtt client (less known in the web developers community). See our code samples here.

➕ : FIFO preserves the sequencing of messages, facilitates the processing of events in the client’s IT (typically state processing)

for large deployments

Azure Event Hubs action

The purpose of this action is to push a message into Azure Event Hubs service. The body can be templated using the Mustache templating syntax.

Depending on the user needs, a retry policy can be enabled to be more resilient to listening endpoint downtimes.

Error management, message overflow, rate limiting, auditlog, certificate aspects are identical to http push action.

Representation of a Azure Event Hubs action
{
	"eventHubsNamespace": "myEventHubsNamespace",
	"eventHubName":"myEventHubName",
	"sharedAccessKeyName":"mySharedAccessKeyName",
	"sharedAccessKey":"mySharedAccessKey",
	"content": "{\"temperature\": {{temp}} }",
	"jsonPath":"value",
	"retryOnFailure":false
}
field name is required description

eventHubsNamespace

required

The Event Hubs namespace where is located the targeted Event Hub.

eventHubName

required

The name of the targeted Event Hub.

sharedAccessKeyName

required

The name of the shared access policy of the targeted Event Hub.

sharedAccessKey

required

The shared access key of the shared access policy.

jsonPath

optional

The json path to extract from the considered message (or event), it will be taken as the root datacontext object when combined with a mustache template in content.

content

optional

A raw string or a mustache (https://mustache.github.io/mustache.5.html) template describing the webhook body. If empty, the raw event will be used.

retryOnFailure

required

Indicate if a retry policy should be set up in case of a delivery failure.

Examples

These examples aim at giving a wide range of example to enable an easy implementation of common use cases for users of the triggers and action service.

Post all your data streams on elastic cloud

Even though Live Objects offers you the ability to store and explore your data leveraging the power of Elastic Search, you may want to keep your data on your dedicated space on Elastic’s Cloud.
This example will demonstrate how to route all your incoming data into your elastic search instance and store only the value part of the data.

Pushing data to elastic search cloud needs to pass credentials through basic auth mechanism. This example will demonstrate how to leverage custom headers mechanism to pass credentials for authentication.

1. Create the dedicated action policy
Given
  • a dedicated Elastic instance at url myinstance.cloud.es.io:9243

  • an elastic cloud username liveobjects with password rocks

  • an elastic search index my_lo_example

  • an elastic search type my_lo_type

Endpoint:

POST /api/v1/event2action/actionPolicies

Body:

{
    "name": "push data to elastic cloud",
    "enabled": true,
    "triggers": {
        "dataMessage": {
           "version": 1
        }
    },
    "actions": {
        "httpPush": [
            {
                "webhookUrl": "https://myinstance.cloud.es.io:9243/my_lo_example/my_lo_type",
                "headers": {"Authorization": ["Basic bGl2ZW9iamVjdHM6cm9ja3MK="]},
                "jsonPath": "value"
            }]
    }
}

Connecting the http push action to a service requiring a JWT token will only need to change the Authorization header to Bearer and pass the token.

2. Push some data

Endpoint:

POST /api/v0/data/streams/my-stream

Body:

{
    "location": {
      "provider": "lora",
      "accuracy": 10,
      "lon": -122.169846,
      "lat": 37.602902},
   "model": "lora_v0",
   "value": {
      "payload": "ae2109000cf6",
      "customMetadata": { "name": "sensor1" }
   },
   "tags": [
      "San Francisco", "Tracker"
     ]
}
3. Check data on elastic cloud

Curl:

curl -X POST -u liveobjects:rocks https://myinstance.cloud.es.io:9243/my_lo_example/my_lo_type/_search -H 'Content-Type: application/json' -d '{ "query": {"match_all": {}}}'

Send a notification to a FIFO when a device is auto-provisioned in Live Objects

This example will demonstrate how to route your device created events to a FIFO queue in order to update your business application device repository when a device is auto-created (here a MQTT device).

  • Provision an action policy to notify the creation of a new device to a FIFO.

  • Get a Live Objects API key with BUS_R role to read the data on the FIFO

  • Get another Live Objects API key with DEVICE_ACCESS role to use with a mqtt device or a mqtt client to simulate a device

  • Connect a mqtt client with the API key with BUS_R role and subscribe to the FIFO. You should receive the device created event message.

  • Connect the mqtt device (or mqtt client) to Live Objects with the API key as password and the device identifier as clientId. The device will be auto-provisioned in Live Objects.

  • Read the deviceCreated message in the FIFO queue.

  • Make a REST API call to retrieve the device detailed information: GET /api/v1/deviceMgt/devices/{deviceId}

These actions can be done in the Live Objects portal, or with the API:

1. Provision an action policy to be notified when a device is created

Endpoint:

POST /api/v1/event2action/actionPolicies

Body:

{
    "name": "device_created_notification",
    "enabled": true,
    "triggers": {
       "deviceCreated": {
          "version": 1
       }
    },
    "actions": {
        "fifoPublish": [
            {"fifoName": "your_fifo_name"}
        ]
    }
}

If you want to be notified on both deviceCreated and deviceDeleted events, you can set the 2 triggers in the same action policy.

{
    "name": "device_created_or_deleted_notification",
    "enabled": true,
    "triggers": {
       "deviceCreated": {
          "version": 1
       },
       "deviceDeleted": {
          "version": 1
       }
    },
    "actions": {
        "fifoPublish": [
            {"fifoName": "your_fifo_name"}
        ]
    }
}
2. Create an API Key with BUS_R role to read data in MQTT in the FIFO

Endpoint:

POST /api/v0/apiKeys

Body:

{
  "active": true ,
  "parentId":"\{\{parentId\}\}",
  "label": "myFIFOKey",
  "roles": [
    "BUS_R"
  ]
}

\{{parentId}\} can be found in the response of user authentication request POST /api/v0/auth

3. Create an API Key with DEVICE_ACCESS role to use with a mqtt device

Endpoint:

POST /api/v0/apiKeys

Body:

{
  "active": true ,
  "parentId":"{{parentId}}",
  "label": "myMqttDeviceKey",
  "roles": [
    "DEVICE_ACCESS"
  ]
}
4. Connect a MQTT client to retrieve the deviceCreated message from the FIFO
 Use your API key with BUS_R role as your mqtt password.
* Connect your MQTT client to Live Objects in _application_ mode.
landing
  • Subscribe to fifo/your_fifo_name

5. Connect a MQTT client (simulating a MQTT device)
  • Use your API key with DEVICE_ACCESS role as your mqtt password.

  • Enter a device identifier in the client ID field.

  • Connect your MQTT client to Live Objects in device mode. The device will be auto-provisioned.

landing
6. Read the message in the FIFO

The following event is present in the FIFO.

{
    "type": "deviceCreated",
    "version": 1,
    "timestamp": "2019-12-04T10:40:58.990Z",
    "deviceId": "urn:lo:nsid:mqtt:myDevice"
}
7. Get the detailed information related to your device

Endpoint:

GET /api/v1/deviceMgt/devices/urn:lo:nsid:mqtt:myDevice

Response:

{
  "id": "urn:lo:nsid:mqtt:myDevice",
  "name": "Auto-created device (mqtt / myDevice)",
  "description": "This device was auto registered by the connector [mqtt] with the nodeId [myDevice]",
  "group": {
    "id": "root",
    "path": "/"
  },
  "interfaces": [
    {
      "connector": "mqtt",
      "nodeId": "myDevice",
      "enabled": true,
      "status": "OFFLINE",
      "lastContact": "2019-12-04T10:41:00.701Z",
      "capabilities": {
        "configuration": {
          "available": false
        },
        "command": {
          "available": false
        },
        "resource": {
          "available": false
        }
      },
      "activity": {
        "apiKeyId": "5de77767d5d6e23710cfdd9e",
        "mqttVersion": 4,
        "mqttUsername": "json+device",
        "mqttTimeout": 60,
        "remoteAddress": "/127.0.0.1:55656",
        "lastSessionStartTime": "2019-12-04T10:40:58.875Z",
        "lastSessionEndTime": "2019-12-04T10:41:00.700Z",
        "security" : {
          "secured": true,
          "protocol": "TLSv1.2",
          "cipher": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
          "clientCertAuthentication": true,
          "sniHostname": "mqtt.liveobjects.orange-business.com"
        }
      },
      "created": "2019-12-04T10:40:58.942Z",
      "updated": "2019-12-04T10:41:00.714Z"
    }
  ],
  "created": "2019-12-04T10:40:58.944Z",
  "updated": "2019-12-04T10:41:00.714Z",
  "activityState": "NOT_MONITORED"
}

Send a notification to a FIFO on device status modification

How to do the test?

  • Provision an action policy with a FIFO action to be notified if the device has a modification of status

  • Get a Live Objects API key with BUS_READ role to read the data on the FIFO

  • Get a Live Objects API key with DEVICE_ACCESS role to use with a mqtt device or a mqtt client to simulate a device

  • Connect the mqtt device (or mqtt client) to Live Objects with the API key as password and the device identifier as clientId.

  • Disconnect the mqtt device

  • Connect a mqtt client with the API key with BUS_READ role and subscribe to the FIFO. You should receive the event status change message.

Action policy provisioning

To create a new action policy linked with a device event:

Endpoint:

POST /api/v1/event2action/actionPolicies

Body:

{
    "name": "my_device_status_policy",
    "enabled": true,
    "triggers": {
       "deviceStatus": {
          "version": 1,
          "filter": {
            "groupPaths": [{
               "includeSubPath": false,
               "path": "your_group_path"
            }]
          }
       }
    },
    "actions:" {
        "fifoPublish": [
            {"fifoName": "your_fifo_name"}
        ]
    }
}
Example of a device status change event message notified by the action policy

Event:

{
    "type": "deviceStatus",                                             (1)
    "version": 1,                                                       (2)
    "deviceId": "urn:lo:nsid:mqtt:deviceId2",                           (3)
    "updatedInterface": {                                               (4)
        "connector": "mqtt",
        "nodeId": "your_device_identifier",
        "enabled": true,
        "status": {                                                     (5)
            "current": "OFFLINE",
            "previous": "ONLINE"
        }
    },
    "timestamp": "2019-08-29T14:11:58.101Z"
}

Description:

1 event message type
2 message type format version
3 device identifier
4 interface information
5 the status transition

Catch the failure commands and publish the events in realtime

Suppose that you have a device fleet and you need, for each device who receive command, catch all registred commands which has been expired then sent all the failure events notifications to an HTTP site as notification target.

To register your action policy:

Endpoint:

POST /api/v1/event2action/actionPolicies
Example of a policy to be created in Live Objects
{
    "name": "Command status event to push HTTP",
    "enabled": true,
    "triggers": {
      "commandStatus": {
        "version": 1,
        "filter": {
          "status": [
            "EXPIRED",  <--- filtered status
            "ERROR"
          ]
        }
      }
    },
    "actions": {
      "emails": [],
      "sms": [],
      "httpPush": [
        {
          "webhookUrl": "https://webhook.site/ad4ae2f9-179c-4d8a-ba2f-2b9064a8508c", <-- wehbhookUrl where you push your notification messages
          "headers": {},
          "retryOnFailure": true
        }
      ]
    }
}

When Live Objects command mechanism control detects a final event after processing the command ended with value = EXPIRED or ERROR, the trigger sends the following message to the url above:

Event:

{
  "type": "commandStatus",
  "version": 1,
  "id": "5dd4fa1cff8b5acbd100998b",
  "targetDeviceId": "urn:lo:nsid:bike:vin123",
  "status": "EXPIRED",
  "request": {
    "connector": "mqtt",
    "value": {
      "req": "test",
      "arg": {
        "cmd": "reset"
      }
    }
  }
}

Retrieve the LoRa® network events (specific if you have a LoRa® fleet)

Suppose that you wish to retrieve, in a FIFO queue, the raw data emitted by LoRa® devices in confirmed mode or in unconfirmed mode. You also want the join accept events.

To register your action policy:

Endpoint:

POST /api/v1/event2action/actionPolicies
Example of a policy for loraNetwork events
{
    "name": "my new policy to route lora network events",
    "enabled": true,
    "triggers": {
        "loraNetwork": {
            "version": 1,
            "filter": {
                "messageTypes": [
                    "UNCONFIRMED_DATA_UP",
                    "CONFIRMED_DATA_UP",
                    "JOIN_ACCEPT"
                ]
            }
        }
    },
    "actions": {
        "fifoPublish": [
            {
                "fifoName": "myFIFO1234"
            }
        ]
    }
}