ExoSense Data IO Schema¶
Introduction¶
This document defines the information required to interface with ExoSense™️ from the “first mile” perspective of the connected device or gateway, as well as describing how this information is carried on into the “last mile” or client-side Application.
This document is meant for device developers building native support into the device or a proxy/gateway service for connection to ExoSense via an IoT service and for those looking to gain a deeper understanding of the architecture of channels and signals in the ExoSense environment. It is not required for typical regular use of the ExoSense application itself.
Who is this for
This document is meant for developers building device software to interact with ExoSense and/or contributing to the development of ExoSense and related technologies.
It is not required for regular use of the ExoSense application itself, although may be helpful for creating end-user documentation.
Definitions¶
The reader of this document should have a grasp on the following items or will need to for this document to make sense.
Term | Description |
---|---|
Murano | Exosite's IoT Platform |
ExoSense™️ | Industrial IoT Application solution created and offered by Exosite |
Device / Gateway / Source | An electronic device with an IP Connection sending data to a platform, interfacing with directly connected sensors, custom protocol connected sensors, or fieldbus connected equipment |
Federation | Software that is connecting to send data on behalf of many source device identities. Requires uses of Federation API and IoT Connector type. |
Sensors | Physical sensors connected to a Source Device or Gateway via wired or wireless protocol or IO (onboard). Sensors are typically specific to a unit of measure - e.g. temperature, pressure, etc. Sensor data is sent as Channels. |
Identity | An Exosite Murano IoT Connector and ExoSense concept to represent and identity the **source* of the information. Typically this is an authenticated device but also with Federation connectors may be created by the federation connection. |
Channel | An ExoSense concept to identify an individual stream of information sent to ExoSense by an unique device identity that is specific to a type and with a specific unit of measure from that local physical environment (e.g. Temperature or Valve 1 status). Can also be information such as memory on the device, status information, etc. |
Signal | An ExoSense concept similar to channel but is the part of a virtual Asset object that describes and stores the data. Signals can be transformed, exported, visualized, and have rules ran on them. The source for a signal is typically a device channel but doesn't have to be. The signal essentially subscribes to it's source. |
Asset | An ExoSense concept for digitizing an Asset (a machine, system, equipment, etc) |
Fieldbus | Industrial protocols like Modbus TCP or RTU, J1939, CANOpen, etc that allow machines, controls, equipment to have a standard way to talk to each other. |
Device Identifier Information¶
Identities for source devices are used in ExoSense as is, these are used to claim and assign a device to a group for ownership. Until an identity has been assigned ownership in ExoSense, it can not be used to map it's channels to asset signals.
Tags¶
ExoSense leverages two tags for Identities, which are supported in the IoT Connector. These are optional to use, providing information helpful to those managing source devices and creating assets from the source device identities. Labels may be added in the Murano IoT Connector solution user interface, when uploading bulk identities in the Murano IoT COnnector solution interface, or from within ExoSense.
Tag | Description |
---|---|
label | Is used to provide a descriptive label about the device identity, such as where it is installed, or a position it may be installed in. Should be a short word or two. |
note | A more descriptive piece of information about the device identity, any notes about this identity. |
Device Interface I/O¶
ExoSense uses the Murano IoT Platform device interface for its device connectivity. The following details the specific device API I/O resources used regardless of the transport protocol (MQTT, HTTP, Cloud Federation) to interact with edge IoT devices.
Murano IoT Device APIs
This document does not cover most details of how to interact with Murano’s IoT product/device interfaces including how to provision a device inside of a product defined in Murano, how to communicate with the_ HTTP or MQTT APIs or other topics covered in Exosite's Murano IoT Connector documentation.
Murano IoT Connector Reference and API Information
Device I/O resource use is as follows:
Resource Name | ExoSense Status | Who Can Write To | Description |
---|---|---|---|
data_in | supported | Device | Used to send data from device to cloud in the format defined below in the data_in section below |
config_io | supported | Device / App | Used to share the complete configuration for a channels in the product. This should be a 2-way synchronization meaning in the case of a self-configuring gateway, this would be written to by the gateway. In a gateway that requires manual configuration from the application, this would be read by the gateway and cached locally. |
data_out | supported | App | Used to send control requests from cloud to device in format defined in data_out control section below |
config_applications | supported | Device / App | Specifies configuration for the interfaces used by gateway protocol/fieldbus applications (i.e. “interface = /dev/tty0”) |
config_oem | reserved | tbd | Settings for product names, and limits that constrain/override communications or collections of data per the manufacturers/OEMs requirements |
config_interfaces | reserved | tbd | |
config_rules | reserved | tbd | |
config_network | reserved | tbd |
Custom device resource I/O naming
When creating custom resources in your Murano IoT Connector for devices, do not use resources with prefix of config_
.
Channel Configuration - config_io¶
Configuration Overview¶
This section defines the Channel Configuration object (sometimes called a device or gateway template). This is the 'contract' for each individual device as to what channels of data it will be sending and optionally be controlling. The concept is data used by ExoSense flows as Channels to and from devices. These device channel sources can then be mapped to digital twin Asset signals in the ExoSense application.
A gateway or device will require some level of configuration in order to do several things:
- Know what information to read off of / write to a fieldbus or IO
- Translate that information from machine-readable and terse input to Murano, back into contextual and human readable data ready to be taken into ExoSense - i.e. a signal object
- Provides a consistent way for standardizing interfaces so that analytic apps downstream are able to consume this common data type.
Of note for this section - the channel (io) configuration will be stored in the config_io product resource for the device as defined in Section 2 of this document. The value in that resource will be considered the source of truth for the shared gateway configuration. Meaning if a gateway is re-configured manually at the gateway, or if it is a gateway that is auto-configured by discovering the devices connected to it, the updated value must be pushed to that resource before RCM will become aware of any changes.
The configuration below wraps a user-defined value with a ${...}, and other names/keys are meant to be an exact match that will be used by ExoSense. Some values for a key are filled in with example strings - noted with an “e.g.”.
config_io
Channel Configuration Definition
# config_io channel definition
last_edited: "${date_timestamp}" # *required* - e.g. 2018-03-28T13:27:39+00:00
last_editor: "${edited_by}" # optional but recommended - String to mark as last editor, Person user name, "user", or "device"
meta: "${meta_string_information}" # optional - This is an open section for manufacturers to include useful meta info about the channels if they see fit
locked: ${locked_config_state} # optional - Boolean, marks config as not editable by UI, assume false if not present
channels: # "device channel" as opposed to an "asset signal"
######### Example channel config 1 - Basic Usage Options ############
${device_channel_id1}: # unique channel identifier string
display_name: "${channel_name_string}" # *required* - Human readable channel name
description: "${channel_description_string}" # optional - One-liner description
properties:
data_type: "${defined_type_enum}" # *required* - See "types" section - in this case it could be "BOOLEAN" or "TEMPERATURE"
data_unit: "${unit_enum}" # *required* - Enumerated lookup to unit types for the given type
precision: ${precision_number_of_decimal_places} # optional but recommended, example value is 2
locked: ${locked_config_state} # optional but recommended - Boolean, marks as not editable by UI, defaults to false if not present
protocol_config: # optional - if used by device client
sample_rate: ${sample_time_in_ms} # optional - device client's sample rate for sensor
report_rate: ${report_time_in_ms} # optional but recommended - rate at which data sent to platform
timeout: ${timeout_period_time_in_ms} # optional but recommended - used by application to provide timeout indication, typically several times expected report rate
######### Example channel config 2 - Expanded Options - Remote Device Configuration Usage ############
# config_io channel definition
last_edited: "${date_timestamp}" # *required* - e.g. 2018-03-28T13:27:39+00:00
last_editor: "${edited_by}" # optional but recommended - String to mark as last editor, Person user name, "user", or "device"
meta: "${meta_string_information}" # optional - This is an open section for manufacturers to include useful meta info about the channels if they see fit
locked: ${locked_config_state} # optional - Boolean, marks config as not editable by UI, assume false if not present
channels: # "device channel" as opposed to an "asset signal"
######### Example channel config 1 - Basic Usage Options ############
${device_channel_id1}: # unique channel identifier string
display_name: "${channel_name_string}" # *required* - Human readable channel name
description: "${channel_description_string}" # optional - One-liner description
properties:
data_type: "${defined_type_enum}" # *required* - See "types" section - in this case it could be "BOOLEAN" or "TEMPERATURE"
data_unit: "${unit_enum}" # *required* - Enumerated lookup to unit types for the given type
precision: ${precision_number_of decimal_places} # optional but recommended, example value is 2
locked: ${locked_config_state} # optional but recommended - Boolean, marks as not editable by UI, defaults to false if not present
protocol_config: # optional - if used by device client
sample_rate: ${sample_time_in_ms} # optional - device client's sample rate for sensor
report_rate: ${report_time_in_ms} # optional but recommended - rate at which data sent to platform
timeout: ${timeout_period_time_in_ms} # optional but recommended - used by application to provide timeout indication, typically several times expected report rate
${device_channel_id2}: # unique channel identifier string
display_name: "${channel_name_string}" # *required* - Human readable channel name
description: "${channel_description_string}" # optional - One-liner description
properties:
data_type: "${defined_type_enum}" # *required* - See "types" section - in this case it would be "TEMPERATURE"
data_unit: "${unit_enum}" # *required* - Enumerated lookup to unit types for the given type
precision: ${precision_number_of decimal_places} # optional but recommended
locked: ${locked_config_state} # optional but recommended - Boolean, marks as not editable by UI, defaults to false if not present
## Additional Channel Properties
control: ${true|false}" # optional - defaults to false, whether channel is used for device control
min: ${channel_min_number} # optional - channel expected value min, applies to numeric type only
max: ${channel_max_number} # optional - channel expected value max, applies to numeric type only
device_diagnostic: false # optional - Tells ExoSense that this is a “meta” signal that describes an attribute of the devices health
protocol_config: # optional - if used by device client
sample_rate: ${sample_time_in_ms} # optional - device client's sample rate for sensor
report_rate: ${report_time_in_ms} # optional but recommended - rate at which data sent to platform
timeout: ${timeout_period_time_in_ms} # optional but recommended - used by application to provide timeout indication, typically several times expected report rate
## Additional Channel Protocol Configuration Properties
report_on_change: ${true|false} # optional - default false (always report on start-up)
down_sample: "${MIN|MAX|AVG|ACT}" # optional - Minimum in window, Maximum in window, running average in window, or actual value (assume report rate = sample rate)
application: "${fieldbus_logger_application_name}" # optional - e.g. "Modbus_RTU"
interface: "${path_to_interface}" # optional but required if using "application" e.g. "/dev/tty0/"
app_specific_config: # optional but maybe be required depending on "application"
${app_specific_config_item1}: "${app_config_item1_value}"
${app_specific_config_item2}: "${config_item2_value}"
## Additional Channel Protocol properties to transform raw data to the channel type / unit before reporting
input_raw: # optional, used to pre-transform data type/unit from raw sensor to channel type, example voltage or bits (ADC) to Pressure
max: ${raw_input_max} # optional - use with max property to convert data format on edge
min: ${raw_input_max} # optional - use with min property to convert data format on edge
unit: "${raw_input_units}" # optional - e.g. "mA", reference only
multiplier: ${number_to_be_multiplied_into_the_raw_value} # optional used to pre-transform data type/unit from raw sensor to channel type, example 4-20 mA to Temperature
offset: ${offset} # optional used to pre-transform data type/unit from raw sensor to channel type, example 4-20 mA to Temperature
control_properties: ## Optional - used to specify control parameters
range: # optional - for Numeric types only
min: ${expected_minimum_value} # optional
max: ${expected_maximum_value} # optional
enum: # optional - provide a list of acceptable values
- ${accepted_value_1}
- ${accepted_value_2}
- ${accepted_value_n}
config_io
Examples
{
"last_edited": "2018-03-28T13:27:39+00:00 ",
"meta": {},
"channels": {
"001": {
"display_name": "Temperature",
"description": "Temperature Sensor Reading",
"properties": {
"data_type": "TEMPERATURE",
"data_unit": "DEG_CELSIUS",
"precision": 2
}
}
}
}
{
"last_edited": "2018-03-28T13:27:39+00:00 ",
"last_editor": "user",
"meta": {},
"locked": false,
"channels": {
"001": {
"display_name": "Valve Open Status",
"description": "Machine Valve Open State Information",
"properties": {
"data_type": "BOOLEAN",
},
"protocol_config": {
"sample_rate": 5000,
"report_rate": 5000,
"report_on_change": false,
"timeout": 60000
}
},
"002": {
"display_name": "Temperature",
"description": "Temperature Sensor Reading",
"properties": {
"data_type": "TEMPERATURE",
"data_unit": "DEG_CELSIUS",
"precision": 2,
"min": 16,
"max": 35,
"device_diagnostic": false,
"locked": true
},
"protocol_config": {
"sample_rate": 2000,
"report_rate": 10000,
"down_sample": "AVG",
"report_on_change": false,
"timeout": 300000,
"application": "Modbus_RTU",
"interface": "/dev/tty0/",
"app_specific_config": {},
"input_raw": {
"max": 0,
"min": 20,
"unit": "mA"
}
}
},
"003": {
"display_name": "Location",
"description": "Location",
"properties": {
"data_type": "LOCATION",
"data_unit": "LAT_LONG"
},
"protocol_config": {
"report_rate": 60000,
"timeout": 360000
}
},
"004": {
"display_name": "Valve Control",
"description": "On / Off control",
"properties": {
"data_type": "BOOLEAN",
"control": true
},
"protocol_config": {
"report_rate": 60000,
"timeout": 360000
}
},
"005": {
"display_name": "Temperature Threshold",
"description": "On / Off control",
"properties": {
"data_type": "TEMPERATURE",
"data_unit": "DEG_CELSIUS",
"control": true
},
"protocol_config": {
"report_rate": 60000,
"timeout": 360000
},
"control_properties": {
"range": {
"min": 30,
"max": 100
}
}
}
}
}
Validation schema - config_io
Download the config_io schema validation file
$id: "https://docs.exosite.io/schema/config-io-schema.yaml"
# $schema: "http://json-schema.org/draft-06/schema#"
title: "Config-IO"
description: ""
type: "object"
required: [ last_edited, channels ]
properties:
last_edited:
type: string
description: "e.g. 2018-03-28T13:27:39+00:00 or 1638311186313"
last_editor:
type: string
description: String to mark as last editor, Person user name, "user", or "device"
meta:
type: string
description: "This is an open section for manufacturers to include useful meta info about the channels if they see fit"
locked:
type: boolean
description: "marks config as not editable by UI, assume false if not present"
default: false
channels:
type: object
describe: ""
patternProperties:
# "^[a-zA-Z0-9_]+$": # This is what I'd like.
"^[-+#%()\t \/0-9:A-Z_a-z]+$": # This is what is on PROD
type: object
description: "A channel"
required: [ display_name, properties ]
properties:
display_name:
type: string
description: "Human readable channel name"
description:
type: string
description: "One-liner description"
properties:
type: object
description: ""
required: [ data_type ]
properties:
data_type:
type: string
description: See "types" section - in this case it could be "BOOLEAN" or "TEMPERATURE"
pattern: '^[A-Z_]+$'
primitive_type:
type: string
description: See "types" section - in this case it would be "BOOLEAN" or "NUMERIC"
enum:
- BOOLEAN
- NUMERIC
- STRING
- JSON
data_unit:
type: [string, 'null']
description: Enumerated lookup to unit types for the given type
pattern: '^[A-Z_]+$'
precision:
type: [integer, 'null']
description: precision_number_of decimal_places optional but recommended, example value is 2
locked:
type: boolean
description: marks as not editable by UI, defaults to false if not present
control:
type: boolean
description: defaults to false, whether channel is used for device control
min:
type: [number, 'null']
description: channel expected value min, applies to numberic type only
max:
type: [number, 'null']
description: channel expected value max, applies to numberic type only
device_diagnostic:
type: boolean
description: Tells ExoSense that this is a “meta” signal that describes an attribute of the devices health
protocol_config:
type: object
description: if used by device client
properties:
sample_rate:
type: integer
description: device client's sample rate for sensor in ms
report_rate:
type: integer
description: optional but recommended - rate at which data sent to platform in ms
timeout:
type: [integer, 'null']
description: optional but recommended - used by application to provide timeout indication, typically several times expected report rate in ms
report_on_change:
type: boolean
description: default false (always report on start-up)
down_sample:
type: string
description: Minimum in window, Maximum in window, running average in window, or actual value (assume report rate = sample rate)
enum:
- MIN
- MAX
- AVG
- ACT
application:
type: string
description: fieldbus_logger_application_name, e.g. "Modbus_RTU"
interface:
type: [string, 'null']
description: optional but required if using "application" e.g. "/dev/tty0/"
app_specific_config:
type: object
description: optional but maybe be required depending on "application"
input_raw:
type: object
description: used to pre-transform data type/unit from raw sensor to channel type, example voltage or bits (ADC) to Pressure
properties:
max:
type: number
description: use with max property to convert data format on edge
min:
type: number
description: use with min property to convert data format on edge
unit:
type: number
description: e.g. "mA", reference only
multiplier:
type: number
description: used to pre-transform data type/unit from raw sensor to channel type, example 4-20 mA to Temperature
offset:
type: number
description: used to pre-transform data type/unit from raw sensor to channel type, example 4-20 mA to Temperature
control_properties:
type: object
description: Optional - used to specify control parameters
properties:
range:
type: object
description: for Numeric types only
properties:
min:
type: [number, 'null']
description: expected_minimum_value
max:
type: [number, 'null']
description: expected_maximum_value
enum:
type: array
description: provide a list of acceptable values
items:
type: string
Data Types and Units for config_io
Check and validate data_type
and data_unit
in the Supported ExoSense Data Types document.
Channel identifiers¶
Channel identifiers must be unique to the device context, in the device's config_io and recommend using no special characters or spaces, but must be a valid string. ExoSense uses a "###"
scheme starting at "001"
. For devices that hard code their configuration and are not remotely configurable, any string can be used and can be more descriptive (e.g. "humidity"). Identifiers are not made viewable by users of the application, the display name is what users will see.
Data types / units¶
Each channel has a unique type and unit tied to the channel identifier that can not be changed after set. The ExoSense application UI will not allow this. Technically a device could overwrite a channel type, but this will have unknown consequences and will likely result in signals not functioning properly. Information about primitive types is also in the Data Types Definition section.
Data types and units for channels and signals are defined in the ExoSense™️ Channel and Signal Data Types document.
Display Name and Description¶
Used by the application to show the user a friendly name and description (optional) of the channel, which will provide them with better context to help map to asset signals.
Locked channels¶
The 'locked' property is not required and is optional for use. The entire configuration can be locked or channels can individually be locked. If not set, defaults to 'false'. A locked channel means that it is read-only on the application side. Assumes the configuration (config_io) has been set by the device and the device has no ability to take action based on changes on the application / cloud side.
Locked channels and full configurations generally are used by devices that have a hard coded configuration, the channels are all defined and the config_io is uploaded by the device. Devices can use a combination of locked and configurable channels, thus why the locked field can be found at both the full config level and per channel.
Report Rate¶
The interval for the device to report values to the cloud (ExoSense). May be used in the application to determine gaps in data.
Timeout¶
The interval that is considered a timeout for a channel. Can be the same as report rate but typically set at a larger interval to provide room for network slowness and reconnection. Typically not used by the device but used by an Asset signal in the application to generate timeout events for the asset / device UI's, timeout events in the asset logs, and future possibilities. E.g. The device reports a channel every 1 minute but if it hasn't reported for 5 minutes, this is an event that may need to have a call to action for.
Control Channels¶
Channels can also be used to 'control' a device. A simple example of this is to turn on/off a valve. By default channels are not enabled to be controlled, but by setting the control
property to true
, ExoSense and the device will allow for sending commands from the application to the device. A control channel uses all of the same schema in this document and devices must write the last state to the data_in
resource, but the use of control channels requires the additional use of data_out
resource. More details below on the proper use and flow of control data.
Protocol configuration¶
Optionally used by the device to determine what application (protocol / interface) will be used and the specific details to get / set the information for the channel. Used for fieldbus protocols (e.g. Modbus RTU) or custom applications such as a custom wireless handler or one that gathers data from local I/O on the hardware. The protocol configuration parameters are optional to use, devices that are not configurable may not use this at all and therefore would not be specified.
Devices that are configurable should use the protocol configuration properties to get / set data, convert it, and determine how often to sample (read locally) and report (to cloud).
Advanced: Additional Channel Edge Conversion Handling
The following parameters are available for device firmware to use to do edge side processing of the data from a sensor or input before sending up to ExoSense. These are all optional and require the device to support. Contact Exosite support before using to discuss how to leverage this functionality.
Report on Change
The report_on_change
parameter, if used and set to True, device firmware should only report channel values if different than the last time it received a value. Typically devices would also send on boot-up and may have more advanced algorithm for when it chooses to report a value.
Down Sample
If used, the down_sample
parameter provides the device with information about how to handle the situation where a channel input is sampled many times over a given time period before (sample vs report rates) reported. This allows a user to decide how to down sample the values before reporting. Options are: Min, Max, Average, or Actual which would require the device to choose a value to send (last, first, etc).
app_specific_config
Is an object that can contain custom parameters (key/value pairs) defined by the device firmware developer to be used by the protocol application.
{
"${app_specific_config_item1}" : "${app_config_item1_value}",
"${app_specific_config_item2}" : "${app_config_item2_value}"
}
Edge Raw Input Conversion Parameters
min
, max
, and unit
under the input_raw
object should be used for applications where the device converts raw sampled data before reporting.
For edge mapping conversion: protocol_config.input_raw.min
and protocol_config.input_raw.max
should be combined with the properties.min
and properties.max
for mapping conversion. For edge unit conversion protocol_config.input_raw.unit
can be used with properties.data_unit
for edge side unit conversion. For edge scale and offset conversion The protocol_config.multiplier
and protocol_config.offset
parameters can be used by the device firmware for edge sample conversion.
Advanced use only for allowing for server side conversion of data. Not supported for normal ExoSense application use. Not recommended. Must not be used by the device.
Channel to Asset Signal Relationship¶
Signals inherit channel properties once created in the application. Once a signal has been created through, changes to the channel's configuration do not automatically get applied to the signal's properties. A signals properties, such as 'timeout', can be changed (if the application allows for it), but will not result in a change back down to the device channel.
Channel Data - data_in¶
Having a common shared channel configuration (a contract essentially) between the device and the cloud/application allows us to keep the actual data sent between devices and the cloud to a minimum - focusing only on the sending of values for channels rather than unnecessary configuration information that rarely changes.
The resource used for writing channel values from devices to the cloud/application is “data_in”, as mentioned in the resource section.
There are 3 different scenarios of how we might want to send data - each one should build on the other, and they are:
Single Data Value
This is a very simple signal_id = value approach, but encoded in JSON.
{ "${device_channel_id1}" : "${current_channel_value}" }
Multiple signals written in a single payload
{
"${device_channel_id1}" : "${current_channel_value1}",
"${device_channel_id2}" : "${current_channel_value2}",
"${device_channel_id3}" : "${current_channel_value3}",
"${device_channel_id7}" : "${current_channel_value7}"
}
Example data_in payload with real data
{
"001" : true,
"002" : 78.233,
"003" : {"lat":43.650883,"lng":-96.201642},
"007" : "good"
}
This payload assumes each datapoint is to be recorded in the time series database at the time it is received.
Note: Each channel is not required to send a value in each payload. Some payloads may have a few channels, some may just have one, others may have all channels
Multiple signals, with some repeating, with different timestamps in a single payload:
Utilize the Record API from Murano, and apply the array of signals to each timestamps data.
Murano Device Record API - HTTP
Murano Device Record API - MQTT
This requires that the clock be synced on the gateway to the global network time via ntp which is used by our servers in our cluster. Our recommendation will be that the ntp server syncs with the gateway at least once every time the power is cycled on the gateway, and once per 12-24 hours of continuous operation time.
Channel Error Handling¶
Optional use, not required
Not Currently Used by ExoSense
When an error occurs for a signal, the payload will change by adding the protected keyword property __error
to the JSON root object like so:
{
"${channel_id1}" : "${current_channel_value1}",
"${channel_id2}" : "${current_channel_value2}",
"${channel_id7}" : "${current_channel_value7}",
"__error" : {
"${channel_id1}" : "${error_message_or_code}",
"${channel_id3}" : "${error_message_or_code}"
}
}
The error object is a list of keys of the channel ids with an error, and then the value of that property is the error message, error code, or concatenation of any useful information that can be formatted into a string.
Note: the device can report a channel data payload, even if the data is erroneous, but that is optional. We will accept a chanel value and an error, just an error for a channel, or just a value. All combinations are supported.
Device Control Interface¶
Optional use, not required
Application use cases that require ExoSense to control device actions, such as turning on/off a valve can use control channels. A control channel works and uses the same schema / format as regular channels. Data types, units, and other properties are all used exactly the same.
Important Disclaimer: Device control from a remote server application requires common sense on what functionality and if a machine should actually be remotely controlled. It is assumed that those building devices and systems that support remote control will provide local override capabilities and safety measures. For example, if a device allows remote control of a garage door that there are physical sensors to sense and not allow a door to close if someone is in the way and ways to override the closing of the door at the physical location.
Example channel configuration for control¶
In this example, there is a valve that the device will open / close based on the channel 004
.
Boolean open / close control channel configuration
"004": {
"display_name": "Valve Control",
"description": "On / Off control",
"properties": {
"data_type": "BOOLEAN",
"control": true
},
"protocol_config": {
"report_rate": 60000,
"timeout": 360000
}
}
Predefined control ranges and options¶
For channels that have a defined range of settings (assuming a numeric type of channel) or a set list of options, the configuration allows setting these ranges or options.
Example Control Range
Example Control Range
In this example for a thermostat type application, a range is provided of acceptable values. ExoSense will enforce allowing users to only set a value in this range.
"009": {
"display_name": "Thermostat Set Point",
"description": "Set Point",
"properties": {
"data_type": "TEMPERATURE",
"data_unit": "DEG_CELSIUS",
"control": true
},
"control_properties": {
"range": {
"min": 20,
"max": 40
}
},
"protocol_config": {
"report_rate": 60000,
"timeout": 360000
}
}
Example Control Value Predefined Options
In this situation, ExoSense and device are aware that only the provided options are available.
"009": {
"display_name": "Garage Door Control",
"description": "Control Options",
"properties": {
"data_type": "STRING",
"control": true
},
"control_properties": {
"enum": [
"open","close","half","auto"
]
},
"protocol_config": {
"report_rate": 60000,
"timeout": 360000
}
}
Device Control Interface¶
Devices that will use control channels must begin subscribing ('mqtt') or polling ('http') the data_out
resource. The data format is the same as data_in
and any new data_out value will contain one or more new control channel requests. The device must acknowledge it received the value by writing the same back to data_out
(Murano Device API requirement) which tells the platform the value was received. After taking action on the control requests, the device must write the new channel states back to data_in to close the loop so ExoSense knows the request finished.
Device Steps: 1. Subscribe or Poll data_out
2. On new data_out
value, acknowledge received by writing back to data_out
3. Device takes control actions. 4. Device writes the channel states that were requested in data_out
back to data_in
Device Protocol Interfaces¶
Optional use, not required
This section defines the supported out of the box protocol interfaces and parameters. OEMs can use their own application and interface parameters also but may not be supported in the application user interface (ExoSense).
Only applicable to devices that are remotely configurable and use a fieldbus or fieldbus like configurable protocol for interacting with data / inputs / sensors.
Modbus TCP¶
Parameters for a channel's protocol configuration 'app_specific_config' field when using Modbus_TCP.
ip_address : "IP_ADDRESS" # ip where the channel is being read as a string
port : "INTEGER" # port to make the request on
register_range : ["HOLDING_COIL", "INPUT_COIL", "INPUT_REGISTER", "HOLDING_REGISTER"]
register : "INTEGER" # 0001-9999
register_count : "INTEGER" # 1, 2, 4, 8, ...
byte_endianness" : [ "little", "big" ]
register_endianness" : [ "little", "big" ]
evaluation_mode : ["floating point: ieee754", "signed integer", "unsigned", "string-ascii"]
bitmask : "HEXADECIMAL" # hex value for bits to mask out/pass-thru
Modbus RTU¶
Parameters for a channel's protocol configuration 'app_specific_config' field when using Modbus_TCP.
slave_id : "INTEGER"
register_range : ["HOLDING_COIL", "INPUT_COIL", "INPUT_REGISTER", "HOLDING_REGISTER"]
register : "INTEGER" # 0001-9999
register_count : "INTEGER" # 1, 2, 4, 8, ...
byte_endianness" : [ "little", "big" ]
register_endianness" : [ "little", "big" ]
evaluation_mode : ["floating point: ieee754", "signed integer", "unsigned", "string-ascii"]
bitmask : "HEXADECIMAL" # hex value for bits to mask out/pass-thru
CANopen¶
Parameters for a channel's protocol configuration 'app_specific_config' field when using CANopen.
node_id : "HEXADECIMAL" # e.g. "0x01"
msg_index : "HEXADECIMAL" # "PDO" starts at 0x180,"SDO" starts at 0x580, required
offset : "INTEGER" # e.g. "0" bytes (determines starting byte position to read), default is 0, required
data_length : "INTEGER" # e.g. "8" bytes (determines how many PDOs to read), default is 8, required
evaluation_mode : [“REAL32”, “INT8”, “INT16”, “UINT16”, “UINT32”, “STRING”, “BOOLEAN”]
Protocol Interface Application Configuration (Optional)¶
Note: Optional use for remotely configurable devices.
The gateway / device applications that handle reading/writing for channels may have properties that need to be set that are useful for all channels using that protocol / interface. For example, 10 channels may be set up to use Modbus_RTU at interface /dev/tty0. The application that handles the Modbus communication needs to know the interface details such as baud rate, etc.
The resource used to hold this information that may then be communicated from cloud application to device is config_applications
. This resource is used by the device to know what interfaces and other application configuration parameters the user has selected. These are not specific to the channel, but to the entire protocol application.
The application protocols and interfaces listed below are used in config_io
and therefore are used to drive channel configuration options in the user application.
Application Configuration (config_applications
) Description
# config_applications channel definition
last_edited: "{$date_timestamp}" # e.g. 2018-03-28T13:27:39+00:00
last_editor" : "${edited_by}" # Person user name, "user", or "device"
applications: # device applications for handling channel protocols, used to show users their protocol / interfaces available for channel configuration.
######### Example application 1 e.g. Modbus_RTU############
${application protocol 1}: # supported or custom protocol e.g. Modbus_RTU
application_display_name: "Human readable application name" # Used in UI
app_specific_config_options: # Optional app specific parameters
${custom_param1}: ${custom_param1_value}
${custom_param2}: ${custom_param2_value}
interfaces:
# first interface for this application protocol
- interface: "${protocol_specific_hardware_interface}" # Specify hardware interface, depends on protocol
custom_interface_param1: ${protocol_specific_value} #specific to protocol
custom_interface_param2: ${protocol_specific_value} #specific to protocol
custom_interface_paramN: ${protocol_specific_value} #specific to protocol
# second interface for this application protocol
- interface: "${protocol_specific_hardware_interface}" # Specify hardware interface, depends on protocol
custom_interface_param1: ${protocol_specific_value} #specific to protocol
custom_interface_param2: ${protocol_specific_value} #specific to protocol
custom_interface_paramN: ${protocol_specific_value} #specific to protocol
######### Example application 2 e.g. CANOpen############
${application protocol 2}: # supported or custom protocol e.g. Modbus_RTU
application_display_name: "Human readable application name" # Used in UI
interfaces:
# first interface for this application protocol
- interface: "${protocol_specific_hardware_interface}" # Specify hardware interface, depends on protocol
custom_interface_param1: ${protocol_specific_value} #specific to protocol
Example Full Application Configuration (config_applications
)
{
"last_edited": "2018-03-28T13:27:39+00:00",
"last_editor": "user",
"applications": {
"Modbus_RTU": {
"application_display_name": "Modbus RTU",
"interfaces": [
{
"interface": "/dev/tty0",
"baud_rate": 115200,
"stop_bits": 1,
"parity": "none",
"data_bits": 8
},
{
"interface": "/dev/tty4",
"baud_rate": 9600,
"stop_bits": 1,
"parity": "even",
"data_bits": 8
}
]
},
"Modbus_TCP": {
"application_display_name": "Modbus TCP",
"interfaces": [
{
"interface": "eth0",
}
]
},
"CANopen": {
"application_display_name": "CANopen",
"interfaces": [
{
"interface": "canA-10",
"channel": "canA-10",
"bitrate": 20000
}
]
},
"CUSTOM_ACME_PROTOCOL": {
"application_display_name": "Acme Custom Protocol",
"interfaces": [
{
"interface": "/dev/tty3",
"param1": "param1value",
"param2": "param2value"
}
],
"app_specific_config_options":
{
"custom_option1":0,
"custom_option2":"option2_value"
}
}
}
}
Specific Protocol Application Interface Configuration¶
This section defines the supported protocol application configuration parameters (i.e. what goes into the interfaces
array objects in config_applications
).
Modbus TCP Application Interface Options¶
Parameters for an application interface when using Modbus_TCP. Device application must use appropriately.
Note: If no interface information provided, assumes device application will properly handle detecting interfaces or is hardcoded.
interface: "STRING" #e.g. eth0
Example
{
"last_edited": "2018-03-28T13:27:39+00:00",
"last_editor": "user",
"applications": {
"Modbus_TCP": {
"application_display_name": "Modbus TCP",
"interfaces": [
{
"interface": "eth1",
},
{
"interface": "wlan0",
}
]
}
}
}
Modbus RTU Application Interface Options¶
Parameters for an application interface when using Modbus_RTU. Device application must use appropriately.
interface: "STRING" #e.g. /dev/tty0
baud_rate: [300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200] #enum of standard baudrates, default to 19200
stop_bits: [1,0,2]
parity: ["even","odd","none"]
data_bits: [8,7]
Example
{
"last_edited": "2018-03-28T13:27:39+00:00",
"last_editor": "user",
"applications": {
"Modbus_RTU": {
"application_display_name": "Modbus RTU",
"interfaces": [
{
"interface": "/dev/tty0",
"baud_rate": 115200,
"stop_bits": 1,
"parity": "none",
"data_bits": 8
},
{
"interface": "/dev/tty12",
"baud_rate": 15200,
"stop_bits": 1,
"parity": "even",
"data_bits": 8
}
]
}
}
}
CANopen Application Interface Options¶
Parameters for an application interface when using CANopen. Device application must use appropriately.
channel: "STRING" #e.g. canA-10
bitrate: [ 10000, 20000, 50000, 125000, 250000, 500000, 800000 and 1000000 ] #bit rate in bps
Example
{
"last_edited": "2018-03-28T13:27:39+00:00",
"last_editor": "user",
"applications": {
"CANopen": {
"application_display_name": "CANopen",
"interfaces": [
{
"interface": "canA-10",
"channel": "canA-10",
"bitrate": 20000
}
]
}
}
}
Custom Application and Protocol Options¶
Hardware application developers may support custom protocols by specifying their own applications in config_applications
with appropriate interfaces
and/or app_specific_config_options
.
Example
{
"last_edited": "2018-03-28T13:27:39+00:00",
"last_editor": "user",
"applications": {
"CUSTOM_ACME_PROTOCOL": {
"application_display_name": "Acme Custom Wireless Protocol",
"interfaces": [
{
"interface": "/dev/tty3",
"param1": "param1value",
"param2": "param2value"
}
],
"app_specific_config_options":
{
"custom_option1":0,
"custom_option2":"option2_value"
}
}
}
}
Change log¶
- Document format / readability updates
- Removed primitive type field (not used)
- Removed iot_properties from channel schema, not supported
- Adding device control support
- Changed Modbus RTU & Modbus TCP protocol configuration 'app_specific_config' key 'register_offset' to 'register'.
- Adding details for the parameters used for device edge input conversion and sampling
- Cleaned up formatting of examples and descriptions
- Moved data types and units to separate document "ExoSense™️ Channel and Signal Data Types"
- Updated "Specific Protocol Application Interface Configuration" (config_applications) interface information
- Added support for 'locked' Channels
- Add iot_properties description for advanced Usage
- Cleaned up options for protocol parameters
- Added primitive type field
- Added graphics to help with description of interface