Skip to content

Sigfox IoT Connector

About

Sigfox is a French global network operator founded in 2009 that builds wireless networks to connect low-power objects such as electricity meters and smartwatches, which need to be continuously on and emitting small amounts of data.

Exosite provides an off the shelf IoT Connector for integrating Sigfox devices into the Exosite Murano platform. This IoT Connector is a Template that includes a Sigfox service that must be configured. Information is provided below.

Info

Before getting started you will need a Sigfox backend Account ready to accept devices connectivity.

Sigfox IoT Connector Overview

The Exosite Sigfox IoT Connector uses a core Murano platform service which provides the following functionality. (Note, this service is automatically added to the IoT Connector solution when creating)

  • A direct interaction with Sigfox API
  • Automated callback management
  • Murano device auto-provisioning
  • Sigfox 12bytes to Murano resourcess mapping
  • Allow multi-tenant biding to Sigfox backend
  • Supported both of uplink and downlink

How Sigfox works

In addition, the IoT Connector template provides the following functionality.

  • Uses the Sigfox Murano Service
  • Automated bundle & event routing
  • Incorporates the ExoSense data model compatibility
  • Data transformation module

Sigfox Account Preparation

Sigfox Setup Notes:

  • Create group, api and devicetype in Sigfox Backend.
  • group is normally a company name.
  • api refers to api access credentials, it includes a apiUser and apiPassword, you can create it in sigfox.
  • devicetype is a collection of same type devices, it is denoted by a unique id created by sigfox when we create a devicetype in sigfox.
  • we need to use those variables in Murano in order to connect sigfox with murano.

Create a group in Sigfox backend

Create a group in Sigfox backend

Create an API access in the group

Create an API access in the group

Create a devicetype in the group

Create a devicetype in the group

Create a devicetype in the group 2

Create a devicetype in the group 2

Check the domain, apiUser and apiPassword

Check the domain, apiUser and apiPassword

IoT Connector Setup and Configuration

Setup Notes

  • We need to fill in the apiUser, apiPassword, sigfox domain and callback definitions in murano Services -> Sigfox setting page.
  • sigfox domain, apiUser and apiPassword is used for accessing sigfox backend api.
  • callbacks includes deviceTypeId and payload configs.
  • payload configs includes resource definitions.
  • resource defines the data received from a Sigfox device for a given deviceTypeId.
  • The resource name indicates the target Murano Device2 resources in which the Sigfox data will be saved.
  • The type defines how to decode the data.

1. Create a Sigfox IoT Connector to your Business

In the Marketplace find Sigfox Connector under the IoT Connector Templates and click on Learn More, and then click Create IoT Connector.

Select Sigfox Connector

2. Configure Sigfox Service

In the new IoT Connector you created, click to open the Management page. On the Sigfox Product 'Services' tab configure your Sigfox account information.

Configure Sigfox Credential

Then add a configuration for your Sigfox 'DeviceType' under the Callbacks list.

Important Notes:

  • Murano configures access to Sigfox per Sigfox 'DeviceType'. 1 Murano IoT-Connector can configure X distinct Sigfox 'DeviceType'.
  • Each entry in the Callbacks configuration matches 1 Sigfox 'DeviceType'
  • Murano Sigfox integration manages the callbacks automatically (Sigfox API defines various callback sub-types).
  • In Sigfox you can only have a single instance of a given callback type per_DeviceType_. Don't configure multiple Murano IoT-Connectors to target the same Sigfox DeviceType.

Configure Sigfox Callback

Configure Sigfox Payload

Have a look to the detailed format for each configuration field on the Murano Sigfox service reference.

Also to define the payload configs representing the 12 bytes sent by the device, read the Sigfox decoding-Grammar page.

Remove a specific callback by clicking on the "..." icon on the right.

Remove Sigfox Callback

Click "APPLY" button after filling up all the configuration.

3. Check the callback in Sigfox backend

Now, your Sigfox deviceType contains a new callback targeting Murano!

Check the callback

Now, if you activate the device to send uplink data, the device along with sent data should be displayed in Murano User-Interface under the IoT-Connector page.

Devices will get automatically provisioned to Murano when receiving the first uplink message.

Resources Setup

Murano product defines the data model available for a given product and usually requires configuration.

Luckily, the Murano-Product-Template automatically configure your product resources from the configured Sigfox resources so no additional set is needed.

(For ExoSense only) Channel Setup

ExoSense application requires the product defining the available data channels available in a config_io resource. Again this template automatically builds the schema from the Sigfox configuration and ExoSense applications connected to the product will display the Sigfox data out-of-the-box.

You can still utilize the ExoSense Channel configuration to customize the look and feel for those channels.

Advanced Configuration

If your payload does not align neatly with the Sigfox decoding grammar, you can manually define the channels and decode the message in Lua.

Defining the Channels

To define the channels, modify the contents of "Modules" -> "vendor.configIO". These channels will merge with any channels defined through the Sigfox decoding grammar.

More details on the structure and available fields for config_io can be found here.
Details on data_types and data_units that are available can be found here.

Warning

Once updating the vendor.configIO module, navigate back to the Sigfox Service configuration and select "Apply" again

Example

Below is an example config_io with a string and a number representing the mode a sensor is in.

 local config_io = [[
  {
    "channels": {
      "mode_string": {
        "display_name": "Mode_string",
        "description": "Mode_string",
        "properties": {
          "data_type": "STRING",
          "data_unit": null
        }
      },
      "mode_num": {
        "display_name": "Mode_num",
        "description": "Mode_num",
        "properties": {
          "data_type": "NUMBER",
          "data_unit": null
        }
      }
    }
 }
 ]]

 return {
   config_io = config_io
 }

Parsing the Payload

To manually parse the payload, modify "Modules" -> "vendor.transform".
This module must contain a function 'transform.convertIdentityState(state)'

The convertIdentityState transforms the data from state.uplink and adds a table state.data_in where state.data_in includes keys corresponding to the channel keys in config_io.

Example

Continuing with the config_io example from above, below is an example of a payload that's mode is defined by bits 7-3 in Byte 1.

To parse out this as both the number corresponding to the mode and it's correlated string, the following vendor.transform module can be used:

local transform = {}

local parser_factory = require("bytes.parser_factory")

local mode_map = {
  [0] = "Standby",
  [1] = "Temperature",
  [2] = "Light",
  [3] = "Door",
  [4] = "Vibration",
  [5] = "Magnet"
}

 function transform.convertIdentityState(state)
   if state == nil then return state end

   if state.uplink ~= nil then
     if state.data_in == nil then state.data_in = {} end
     if (type(state.data_in) == "string") then state.data_in = from_json(state.data_in) end
     local full_byte = parser_factory.getuint(parser_factory.fromhex(state.uplink),1,8)
     -- The mode is only 5 bits long
     local mode_num = bit.rshift(full_byte, 3)
     local mode_string = mode_map[mode_num]

     ------------------------------
     -- This is the important part
     ------------------------------
     state.data_in['mode_string'] = mode_string
     state.data_in['mode_num'] = mode_num

     -- Parse more bytes
     -- ...
     -- ...
   end

   if state.data_in and type(state.data_in) ~= "string" then
     state.data_in = to_json(state.data_in)
   end

   return state
end

return transform

Customization

Warning

The following steps are intended for an advanced Murano developer.

Sigfox Product Template is Open-Sourced and you can customize its behavior to fit your own needs.

Fork the Sigfox-product branch repo into your own account and modify its Lua logic as required.


Last update: April 10, 2021