1. Introduction
Hardwire is an Internet of Things platform that allows you to create smart connected objects. Data can be collected from many different sources, using different software libraries or APIs:
- Any Arduino or compatible device
- Raspberry PI or similars
- Industrial PLC through IEC libraries
- Any device running Android
- Linux operative system
- In general any embedded device
Data collected by Hardwire IoT platform can be accessed at any time through two different communication channels:
- Standard Rest APIs
- A push channel based on a secured WebSocket
The goal of this documentation is to provide a full description of how to integrate third party applications with Hardwire platform, how to send sensor data and how to access collected data through APIs and WebSocket. This document contains technical information, and it’s therefore intended for software developers.
Getting started
In order to start using Hardwire you must be a registered user. You can sign up at any time for a free plan following this URL: .
https://www.hardwire.io/en/iot/signup
If you are interested to use Rest API you can apply for an authorization token writing something about your application at this address:
hardwire@imotion.it
General concepts
CloudMonitor APIs and WebSocket make use of generic concepts and entities:
- Sensor: a sensor is the abstract entity that represents the target of each datum sent to the platform. A sensor can be anything, like a room, an electronic device or a generic object.
- Plant : a plant is typically an entity that contains or or more sensors. Within a plant, sensors are arranged in a tree structure, where plant is usually considered the father of any other element.
- Data logger : it’s the electronic device that collects and sends data to the platform. Every data logger is associated to a single plant but can send data for many different sensors.
- Variable : it’s what we usually call “measure”. It’s always associated to a sensor, and in general it represents the value of a measure at a specific time. Variables and alarms are collected by data logger and sent to the platform. A variable usually has an attribute that identifies its type. See appendix for list of variable types.
- Alarm : alarm is a generic and abnormal situation detected by a data logger. It’s usually sent to the platform by a data logger. Alarms don’t have a status but they just represent something happened in a specific moment.
- Event : events are objects generated only by the platform when a specific situation occurs. Any user can configure one or more situation to be monitored. Once an event occurs, the platform may generate a notification. An example of event configuration is “create an event when temperature goes below 12 degrees”.
- Notification : a notification has the goal to warn a user when an event occurs. Email is a typical example of notification althought there're other different methods.
2. API Reference
The most important method to integrate Hardwire with third party applications is using standard Rest APIs. Below a list of all the public APIs available.
Data format
Data contained in both APIs and WebSocket are represented using the standard JSON format. Also request parameters and any kind of output are formatted in JSON.
Authentication
Hardwire offers applications the ability to issue authenticated requests on behalf of the application itself (as opposed to on behalf of a specific user). The authentication process has been implemented following the OAuth 2 specification.
Each application that wants to use Hardwire APIs must be recognized and identified by the platform and needs an authentication token. Authentication tokens are strictly connected with a specific user of the platform, therefore a token grants access only to data and information related to that specific user.
Authentication token must be specified in any HTTP request, following the OAauth 2 standard:
"Authorization: Bearer <TOKEN>"
If you want to apply for an API token, just write us an email to: hardwire@imotion.it
Rate limit
Rate limiting of the API is primarily considered on a IP basis. Rate limits are calculated into 15 minute intervals. There’s a standard bucket of 60 calls every 15 minutes.
In case you need real-time data, a WebSocket is available.
Response codes
Hardwire platform can use different HTTP response codes, depending on the result of the operation.
HTTP response | Description |
---|---|
200 Ok | Request completed successfully |
400 Malformed Request | Malformed request: check parameters or endpoint |
401 Unauthorized | The authentication token is not allowed to access the resource specified on the request |
403 Validation Error | Returned mainly during the creation of a resource, it specifies that some fields contains invalid data (like an invalid email) |
404 Not Found | Record not found |
500 Internal Server Error | Internal server error is a temporary response code due to an extraordinary condition. Retry later or contact the technical support if this error persists |
API: Plant list
Useful to retrieve the list of plants. The request has no parameter.
URL | https://app.hardwire.io/api/v1/plant_list |
TYPE | HTTP GET |
Response format
{
"plants": [
{
“id”: 32,
“name”: “MyPlant1”,
}, {
“id”: 44,
“name”: “MyPlant2”
},
] }
The response is a JSON object that contains an array with a list of “plant” objects.
Field | Type | Always present | Description |
---|---|---|---|
id | Integer | yes | Unique ID of the object |
name | String | yes | Plant name |
API: Sensor map
This API returns the structure and relation of each sensor that composes a plant. The request has no parameter.
URL | https://app.hardwire.io/api/v1/sensor_map/<PLANT_ID> |
TYPE | HTTP GET |
Request parameters
The only parameter accepted by the request is specified as part of the endpoint URL.
Field | Type | Required | Description |
---|---|---|---|
PLANT_ID | Integer | yes | Plant ID. You can get it from Plant List API. |
Response format
{
"sensors": [{
"id": "330",
"name": "MySensor1",
"sensor_id": 0,
"icon": "remote_control",
"children": [{
"id": "331",
"name": "MySensor2",
"sensor_id": 1,
"icon": "sun",
"children": [
{
"id": "332",
"name": "MySensor3",
"sensor_id": 2,
"icon": "air_conditioning_indoor",
"children": []
}]
}]
}]
}
The response is a JSON object that represents a tree of sensors and children. Each sensor object has these attributes.
Field | Type | Always present | Description |
---|---|---|---|
id | Integer | yes | Unique sensor id. Assigned automatically by the platform. |
name | String | yes | Sensor name |
sensor_id | Integer | yes | Unique within a plant. Assigned by the user. |
icon | String | yes | A string that represents the icons assigned to this sensor. |
children | Array | yes | An array of sensor objects, children of the current one. |
There’s an important difference between “id” and “sensor_id”. The first one is auto-assigned by the platform every time you create a new sensor, while the second one is manually assigned from the user. The only exception is the first sensor of the tree that has always a fixed “sensor_id” set to 0.
API: Data history
This API returns historical data of a specific variable.
URL | https://app.hardwire.io/api/v1/history |
TYPE | HTTP POST |
Request parameters
{
“sensor_id”: 32,
“date”: “2014-12-17”,
“var_type”: 34
}
The parameters must be sent into the body of the POST request as a JSON object:
Field | Type | Required | Description |
---|---|---|---|
sensor_id | Integer | yes | Unique ID of sensor. It can be obtained from the “id” field of the Sensor Map API. NOTE: Sensor Map API returns also a user defined sensor_id attribute. That value is only used by data loggers and it’s nothing in common with this parameter. |
date | Date | yes | Date, in formato YYYY-MM-DD |
var_type | Integer | yes | Identifier of the variable we’re requesting data. See appendix for all supported values. |
Response format
{
"sensor_id": "32",
"date": "2014-12-17",
"var_type": "34",
"summary": {
"sum": 12.60076878295,
"count": 17,
"min": 0.00033618172165006,
"max": 1.7930368185043,
"min_key": "1451431005",
"max_key": “1451484793”,
},
"data": {
"1451430105": 0.00084083323599771,
"1451430165": 0.0021014518570155,
"1451430225": 0.00092494185082614,
"1451430285": 0.00075672467937693,
"1451430345": 0.0010087979026139,
"1451430405": 0.00092468928778544,
"1451430465": 0.0014292144915089,
"1451430526": 0.00058812863426283,
"1451430585": 0.0009092777618207,
"1451430645": 0.00084070692537352,
"1451430705": 0.0014299730537459,
"1451430765": 0.0013693266082555,
"1451430825": 0.0016812877729535,
"1451430885": 0.00067261612275615,
"1451430945": 0.00058863376034424,
"1451431005": 0.00033618172165006,
"1451484793": 1.7930368185043
}
}
The response is a JSON object that contains the values of the variable on that specific interval.
Field | Type | Always present | Description |
---|---|---|---|
sensor_id | Integer | yes | Same value of request |
date | Date | yes | Same value of request |
var_type | Integer | yes | Same value of request |
summary | Array | yes | A summary of the measures, count, min, max ... |
data | Array | yes | An array of values in the format “timestamp” => “value” |
API: Plant status
This API returns historical data of a specific variable.
URL | https://app.hardwire.io/api/v1/plant_status/<PLANT_ID> |
TYPE | HTTP GET |
Request parameters
The only parameter accepted by the request is specified as part of the endpoint URL.
Field | Type | Required | Description |
---|---|---|---|
PLANT_ID | Integer | yes | Plant ID. You can get it from Plant List API. |
Response format
{
"status": [{
“var_type”: 32,
“value”: 1.23,
"sensor_id": 84,
"timestamp": 1451486902
}]
}
The response is a JSON object that contains an array of variables with these fields:
Field | Type | Always present | Description |
---|---|---|---|
var_type | Integer | yes | Id of the variable. It represents the type of variable. See appendix for all possibile values. |
value | String | yes | Value of the variable |
sensor_id | Integer | yes | Unique ID of sensor. Same value obtained from the “id” field of the Sensor Map API. NOTE: Sensor Map API returns also a user defined sensor_id attribute. That value is only used by data loggers and it’s nothing in common with this parameter. |
timestamp | Integer | yes | Timestamp of the variable |
API: Event list
This API returns a list of events generated from the platform for a specified plant. For real-time event acquisition use WebSocket instead of standard APIs.
URL | https://app.hardwire.io/api/v1/event_list |
TYPE | HTTP POST |
Request parameters
{
“plant_id”: 32,
“offset”: 200,
“num_records”: 100
}
The parameters must be sent into the body of the POST request as a JSON object:
Field | Type | Required | Description |
---|---|---|---|
plant_id | Integer | yes | Plant ID. You can get it from Plant List API. |
offset | Integer | no | Used for pagination, it skips the first “offset” elements. Default value is 0. |
num_records | Integer | no | Number of records returned. Default value is 20. Maximum value 500. |
Response format
{
"events": [{
“id”: 67933,
“sensor_id”: 32,
“event_type”: 3,
"active": false,
"description": “Temperature is below threshold of 23.5”,
"timestamp": 1451486901
}, {
“id”: 67953,
“sensor_id”: 18,
“event_type”: 3,
"active": true,
"description": “Panic button pressed”,
"timestamp": 1451484503
}]
}
The response is a JSON object that contains an array of events with these attributes:
Field | Type | Always present | Description |
---|---|---|---|
id | Integer | yes | Unique id of the event. |
sensor_id | Integer | yes | Id of the sensor that generated the event. |
event_type | Integer | yes | Type of the event. See appendix for all possibile values. |
active | Bool | yes | Whether event is still active or not. |
description | String | yes | A description of the event. |
timestamp | Integer | yes | The timestamp of the event. |
Events are returned from the newest one.
API: Alarm list
This API returns a list of alarm collected by the platform for a specified plant. For real-time alarm acquisition use WebSocket instead of standard APIs.
URL | https://app.hardwire.io/api/v1/alarm_list |
TYPE | HTTP POST |
Request parameters
{
“plant_id”: 32,
“offset”: 200,
“num_records”: 100
}
The parameters must be sent into the body of the POST request as a JSON object:
Field | Type | Required | Description |
---|---|---|---|
plant_id | Integer | yes | Plant ID. You can get it from Plant List API. |
offset | Integer | no | Used for pagination, it skips the first “offset” elements. Default value is 0. |
num_records | Integer | no | Number of records returned. Default value is 20. Maximum value 500. |
Response format
{
"alarms": [{
“id”: 3288534,
“sensor_id”: 32,
“alarm_type”: 3,
"description": “Internal data logger memory is full”,
"timestamp": 1451486901
}, {
“id”: 3288554,
“sensor_id”: 18,
“alarm_type”: 3,
"active": true,
"description": “Panic button pressed”,
"timestamp": 1451484503
}]
}
The response is a JSON object that contains an array of alarms with these attributes:
Field | Type | Always present | Description |
---|---|---|---|
id | Integer | yes | Unique id of the alarm. |
sensor_id | Integer | yes | Id of the sensor that generated the alarm. |
alarm_type | Integer | yes | Type of the alarm. See appendix for all possibile values. |
description | String | yes | A description of the alarm. |
timestamp | Integer | yes | The timestamp of the alarm. |
Alarm are returned from the newest one.
API: Send Command
This request sends a command to a specified device and returns the status of the command.
URL | https://app.hardwire.io/api/v1/send_command |
TYPE | HTTP POST |
Request parameters
{
“plant_id”: 32,
“command”: "SET_PWM_OUT_1",
"parameter": "100"
}
The parameters must be sent into the body of the POST request as a JSON object:
Field | Type | Required | Description |
---|---|---|---|
plant_id | Integer | yes | Plant ID. You can get it from Plant List API. |
command | String | yes | String of a specific command. See appendix for all possibile values. |
parameters | String | no | Extra parameters to send together with the command. |
Response format
{
"command": {
"id": 35,
"status": "PEND"
}
}
The response is a JSON object that contains the values of the command.
Field | Type | Always present | Description |
---|---|---|---|
id | Integer | yes | ID of the command. |
status | String | yes | String for the result of the sending. Possible values:
|
If the command is not supported the response will be HTTP 400 code.
API: Command Status
This request returns the status of the specified command.
URL | https://app.hardwire.io/api/v1/command_status/<COMMAND_ID> |
TYPE | HTTP GET |
Request parameters
The only parameter accepted by the request is specified as part of the endpoint URL.
Field | Type | Required | Description |
---|---|---|---|
COMMAND_ID | Integer | yes | Command ID. You can get it from Send Command API. |
Response format
{
"command": {
"id": 35,
"status": "PEND"
}
}
The response is a JSON object that contains the values of the command.
Field | Type | Always present | Description |
---|---|---|---|
id | Integer | yes | ID of the command. |
status | String | yes | String for the result of the sending. Possible values:
|
If the command is not supported the response will be HTTP 400 code.
3. Arduino Library
Hardwire is fully compatible with any Arduino-compatible board. Integrating Hardwire Arduino Library into your project, you can add very powerful features like:
- Real time logging of variables
- Alerting and notification in case of any alarm or abnormal situation
- Remote commands
Please read general concepts about Hardwire platform before proceeding.
Requirements
Hardwire Arduino Library is compatible with any Arduino board. Due to the fact the board must be able to communicate with the platform, an Internet connection is required. You can connect your Arduino board to the Internet in any way:
- with an official or unofficial Ethernet shield
- with any WiFi shield or in general any WiFi module
- with any board that supports Ethernet or WiFi natively (like Arduino Yun, Arduino Ethernet or similars)
Getting started
In order to use Hardwire Arduino library you should install a valid Arduino IDE on your computer. Both Arduino.cc IDE and Arduino.org IDE are fully supported.
Once IDE is working and can communicate with your Arduino board, follow these instructions to install Hardwire Arduino Library:
- Clone or download CloudMonitor Arduino Library from Github.
- Install library into your IDE. For detailed information about adding an external library just follow this link.
- Restart your IDE and check if library is successfully detected.
- Go to File -> Example and load one of the samples contained into the the library for quick information about how to use it.
Standard usage
For a standard usage, Hardwire Arduino Library requires an instance of a generic Client object in order to connect to the Internet. Any class that extends Client can work properly (like EthernetClinet or WiFiClient).
Init function
// This will init the library
cm24_init("MY_PLANT_IDENTIFIER", "MY_PLANT_TOKEN", "MY_COMMAND_TOKEN", clientObjectInstance);
// This is for setting a specific callback function called once Arduino board receives a remote command
cm24_register_command_callback( my_callback_function );
Init of the library should be done within setup function of your sketch. This is the place where you have to specify your plant identifier and tokens. During the setup execution you can also specifiy a custom remote command callback, which is a function called every time Hardwire platform sends a command to the board.
Loop function
void loop()
{
// Don't block loop in any way
cm24_arduino_loop();
}
Hardwire loop function must be called within standard sketch loop function. This is a mandatory requirements, because loop function is responsible to transfer local data to the cloud platform. This function has an internal timing, so it should be called at the maximum speed possibile.
NOTE: try to avoid as much as possible any blocking operation within the main sketch loop function. If loop function is blocked by any other function, Hardwire Arduino Library cannot transfer local data to the platform nor receive any command.
Logging variables or alarms
cm24_log_variable( uint32_t VARIABLE_ID, float value, uint16_t sensor_id );
cm24_log_alarm( uint32_t ALARM_ID, float value, uint16_t sensor_id );
Logging variables and alarms have not been so easy! Just call cm24_log_variable and cm24_log_alarm function. The library will localy save the value of the variable or the code of the alarm and transfer it to the cloud platform as soon as possibile.
NOTE: you should always place a delay between two log function calls. Logging at the maximum speed without any delay will lead to fill local buffer and lose data.
Receiving remote commands
void setup()
{
....
cm24_register_command_callback( callback_function );
}
void callback_function( char *command )
{
// This function will be called every time you get a new command.
}
Remote commands are a very interesting feature of the library, because they grant you control of your Arduino board from any place of the world. Remote commands are represented by standard text strings. It's in charge to your application to understand the command and execute it.
In order to receive remote commands, you firstly have to register a callback function during the setup process. This function will be called every time your board receives a remote command.
If you want to disable remote commands you can both avoid to specifiy the command callback or pass an empty command token to the cm24_init function.
Advanced configuration
// Change this values to have a larger or smaller buffer
#define CM24_BUFFER_ALARM_SIZE 5
#define CM24_BUFFER_VAR_SIZE 50
Hardwire Arduino Library has few optional configuration parameters, useful for fine tuning memory usage and performance. Usually default values are ok, but you can change any configuration parameter just editing the hardwire_config.h file, which is part of the library.
Parameter | Default | Description |
---|---|---|
CM24_BUFFER_ALARM_SIZE | 5 | Number of elements of the local buffer used to save alarms when connections to the platform is temporary not working. Higher the value higher the memory used by the library. |
CM24_BUFFER_VAR_SIZE | 50 | Number of elements of the local buffer used to save variables when connections to the platform is temporary not working. Higher the value higher the memory used by the library. |
Appendix: Variable types
Every variable has a type, that represents the physical measure it represents. The type of the variable helps the platform to understand what is the measure unit and how to format the value.
Below a list of supported variable IDs.
ID | Type | Description |
---|---|---|
1 | String | IP Address (usually of the data logger that sent the record) |
4 | Float | Latitude |
5 | Float | Longitude |
6 | Float | Speed (Km/h) |
7 | Float | GPS Heading (degrees) |
20 | Float | Temperature (°C) |
21 | Float | Solar radiation (W/m2) |
22 | Float | Electrical current (A) |
25 | Float | Electrical power (kW) |
26 | String | Firmware version |
38 | Float | Data logger internal battery voltage (V) |
52 | Boolean | Generic Digital Input 1 |
53 | Boolean | Generic Digital Input 2 |
54 | Boolean | Generic Digital Input 3 |
55 | Boolean | Generic Digital Input 4 |
56 | Float | Generic Analog Input 1 |
57 | Float | Generic Analog Input 2 |
58 | Float | Generic Analog Input 3 |
59 | Float | Generic Analog Input 4 |
63 | Integer | Altitude (m) |
64 | Float | Generic Analog Input 5 |
65 | Float | Generic Analog Input 6 |
66 | Float | Generic Analog Input 7 |
67 | Float | Generic Analog Input 8 |
69 | Float | Humidity (%) |
70 | Float | Pressure (Bar) |
75 | Boolean | Generic Digital Output 1 |
76 | Boolean | Generic Digital Output 1 |
77 | Boolean | Generic Digital Output 1 |
78 | Boolean | Generic Digital Output 1 |
79 | Integer | Generic Counter |
80 | Integer | PWM Output 1 |
81 | Integer | PWM Output 2 |
82 | Integer | PWM Output 3 |
83 | Integer | PWM Output 4 |
84 | Float | Acceleration X-axis |
85 | Float | Acceleration Y-axis |
86 | Float | Acceleration Z-axis |
87 | Float | Ambient light (lux) |
88 | Integer | Battery level (%) |
Appendix: Alarm types
Every alarm sent by the data logger must have a type, which helps to identify the meaning of the alarm.
Below a list of supported alarm IDs.
ID | Type | Description |
---|---|---|
9 | Custom user alarm | Available for custom user alarms. |
10 | Internal battery low | Sent by the data logger when the internal battery (if available) is discharged. |
11 | Storage full | Sent by data logger once the internal storage is almost full. |
12 | Data logger tamper | Sent by data logger in case of tamper detection. |
Appendix: Event types
Every event has a type, that represents the logic that stands behind it.
Below a list of supported event IDs.
ID | Type | Description |
---|---|---|
3 | Variable Value | Created every time a variable has a value out or within a certain interval. |
4 | Sensor Offline | Created every time the platform doesn’t receive an update of some variables for a specified amount of time. |
7 | Input Activation | Created once we have a digital input activtion/ deactivation (see Generic Digital Input variable types). |
Appendix: Command types
Every command has a type, that represents the command itself.
Below a list of supported command IDs.
Command | Description | Parameters |
---|---|---|
SET_DIG_OUT_1 | Set digital output 1 | None |
RESET_DIG_OUT_1 | Reset digital output 1 | None |
SET_DIG_OUT_2 | Set digital output 2 | None |
RESET_DIG_OUT_2 | Reset digital output 2 | None |
SET_DIG_OUT_3 | Set digital output 3 | None |
RESET_DIG_OUT_3 | Reset digital output 3 | None |
SET_DIG_OUT_4 | Set digital output 4 | None |
RESET_DIG_OUT_4 | Reset digital output 4 | None |
SET_DIG_OUT_5 | Set digital output 5 | None |
RESET_DIG_OUT_5 | Reset digital output 5 | None |
SET_DIG_OUT_6 | Set digital output 6 | None |
RESET_DIG_OUT_6 | Reset digital output 6 | None |
SET_DIG_OUT_7 | Set digital output 7 | None |
RESET_DIG_OUT_7 | Reset digital output 7 | None |
SET_DIG_OUT_8 | Set digital output 8 | None |
RESET_DIG_OUT_8 | Reset digital output 8 | None |
SET_DIG_OUT_9 | Set digital output 9 | None |
RESET_DIG_OUT_9 | Reset digital output 9 | None |
SET_DIG_OUT_10 | Set digital output 10 | None |
RESET_DIG_OUT_10 | Reset digital output 10 | None |
SET_PWM_OUT_1 | Set the PWM output 1 to a specified value | Requires an INT value (0..100) |
SET_PWM_OUT_2 | Set the PWM output 2 to a specified value | Requires an INT value (0..100) |
SET_PWM_OUT_3 | Set the PWM output 3 to a specified value | Requires an INT value (0..100) |
SET_PWM_OUT_4 | Set the PWM output 4 to a specified value | Requires an INT value (0..100) |