Connect IoT - DataBase Driver#
The DataBase driver purpose is to allow the communication to a data base server (on this version only MSSQL and MYSQL is available).
It is responsible for creating the necessary SQL queries dynamically, according to the driver definition, to either execute commands or handle events.
Data Types#
These are the supported specific data types:
| Name | Description |
|---|---|
| VARCHAR | Non-Unicode String Value |
| NVARCHAR | Unicode/ Non-Unicode String Value |
| TEXT | Text Value |
| INT | Integer Value (4 bytes) |
| BIGINT | Large Integer Value (8 bytes) |
| TINYINT | Very Small Integer Value (1 byte) |
| SMALLINT | Small Integer value (2 bytes) |
| BIT | Bit Value |
| FLOAT | Float Value |
| DECIMAL | Decimal Value |
| REAL | Real Value |
| DATE | Date Value |
| DATETIME | Date and Time Combination Value |
| TIME | Time Value |
| BINARY | Binary Byte value |
Handling Decimal Precision in Database#
When using the DriverDatabase to write decimal values, you may encounter an issue where the decimal part of the value is truncated, and the value is rounded to the nearest whole number. This occurs because the internal mssql Node.js module defaults to binding DECIMAL values as DECIMAL(18,0). As a result, even if the database column is defined with a precision and scale (e.g., DECIMAL(18,2)), the values are rounded.
To address this issue, use the DECIMAL type for MES and configure the Protocol Data Type as FLOAT instead of DECIMAL. This ensures the value is passed and written to the database without truncation or rounding.
Protocol Parameters#
The protocol supports the following parameters:
| Name | Type | Possible Values | Default Value | Description |
|---|---|---|---|---|
| dataBase | Enum | MSSQL, MYSQL | MSSQL | Data Base type where the driver will connect |
| server | String | 127.0.0.1 | Server where the data base is located | |
| port | Integer | 1433 | Port where the server is listening | |
| instanceName | String | The instance name to connect to. The SQL Server Browser service must be running on the database server, and UDP port 1434 on the database server must be reachable | ||
| encrypt | Boolean | false | Flag determining whether or not the connection will be encrypted | |
| user | String | User name to use for authentication | ||
| password | String | Password to use for authentication | ||
| domain | String | Domain of the user | ||
| databaseName | String | Database to connect to | ||
| connectionTimeout | Integer | 15000 | Connection timeout (ms) | |
| requestTimeout | Integer | 15000 | Request Timeout (ms) | |
| databasePollingInterval | Integer | 300000 | Time between calls to the system to check if database has changed (ms) | |
| applicationName | String | "Connect IoT Database Driver" | Application name used for SQL server logging |
Event#
In order to handle events the dataBase driver creates a query that will be polling the data base (trigger query) and when a change is noticed, a different query is executed to retrieve the intended data (result query).
The trigger query and the result query are both built according to the configuration on the driver definition:
| Name | Type | Possible Values | Default Value | Description |
|---|---|---|---|---|
| table | String | Name of the table that will be monitored by the polling | ||
| argument | String | Name of the column to be used for trigger | ||
| pollingInterval | Integer | 10000 | Polling interval to check for changes on the specified column (in milliseconds) | |
| triggerType | Enum | OnNewRows OnRowChanged | OnNewRows | Type of trigger. 'OnNewRows' it will raise an event if a new row is detected. 'OnRowChanged' it will raise an event if there is a change in the trigger query result. 'None' it will do nothing |
| trigger | Enum | RowNumber Count Field | Count | Trigger to be used. 'RowNumber' it will use the row number function to detect new changes. 'Count' it will use the count of rows to detect new changes. 'Field' it will monitor a specific field for new changes. 'None' it will do nothing. |
| resultDataFormat | Enum | SingleRow AllNew | SingleRow | The way the results will be delivered in the event occurrence. 'SingleRow' it will return one row per event, even if multiple rows are detected. 'AllNew' All detected rows will be returned |
| processingMode | Enum | FireAndForget ContinueOnProcessingConfirmation | Type of processing mode for the results. FireAndForget' the event will be triggered and will not wait for processing confirmation. 'ContinueOnProcessingConfirmation' the event will await for a confirmation reply (a command with a type 'ConfirmDataProcessing' for this event) before raising further events with new data. | |
| processingTimeout | Integer | 60000 | Timeout to wait for a confirmation for events of Processing Mode 'ContinueOnProcessingConfirmation' (in milliseconds). After timeout, events will be discarded | |
| maxRetries | Integer | 3 | Maximum number of retries before expiration for events of Processing Mode 'ContinueOnProcessingConfirmation' | |
| maxRowsToProcess | Integer | 0 | Maximum number of rows to process per batch results (0 means all) | |
| orderByColumn | String | Column used for sorting | ||
| orderByType | Enum | ASC DESC | ASC | Type of order to be used to sort |
| ignoreInitialValues | Boolean | false | Determines whether the initial values should be ignored or not. If set as false and there are values in the table, an event will be immediately triggered | |
| rawResultQuery | String | Query to be executed after the trigger query instead of calculated one based on settings (leave empty to be ignored). Tokens that can be used: 'CurrentValue' value returned by the trigger query LastPersistedValue_' Value persisted, that references the last value processed by the trigger query. 'TriggerQuery' Query used as trigger 'TriggerResults' value returned by the trigger query, this will bypass the creation of a result query and it will emit the value that was collected in the trigger query. | ||
| rawTriggerQuery | String | Query to be executed as the trigger query instead of calculated one based on settings (leave empty to be ignored). |
Event Property#
Event properties represent the table columns that will be retrieved as result. The association between the property and the data base column can be specified as presented below:
| Name | Type | Possible Values | Default Value | Description |
|---|---|---|---|---|
| columnName | String | Relates for this event the property with the column in the event. |
Event Examples#
Example 1: Subscribe to a ROW_NUMBER event
Event Configuration:
table: [Table01], argument: "Column01", pollingInterval: 1000, triggerType: "OnNewRows", trigger: "RowNumber", resultDataFormat: "AllNew", maxRowsToProcess: 2, orderByColumn: "Column01", orderByType: "DESC", processingMode: "FireAndForget", ignoreInitialValues: true
Event Properties Configuration:
name: "EventPropName", deviceId: "EventPropID", columnName: "Column02"
In this example the trigger query, which will be executed every second (pollingInterval: 1000), is the following:
And it will retrieve all the new values for the Column02 (specified on the event property). Notice that the maxRowsToProcess is set as 2, so if the result has more than 2 rows, the event will be raised multiple times, returning only 2 rows per event. Also, this an FireAndForget event, which means that when the event is raised, it requires no reply to continue polling.
Result example:
Example 2: Subscribe to a COUNT event
Event Configuration:
table: [Table01], argument: "Column01", pollingInterval: 1000, triggerType: "OnNewRows", trigger: "Count", resultDataFormat: "SingleRow", orderByColumn: "Column01" , orderByType: "DESC", processingTimeout: 3000, maxRetries: 3, processingMode: "ContinueOnProcessingConfirmation", ignoreInitialValues: false
Event Properties Configuration:
name: "EventPropName01", deviceId: "EventPropID01", columnName: "Column01"
name: "EventPropName02", deviceId: "EventPropID02", columnName: "Column02"
In this example the trigger query, which will be executed every second (pollingInterval: 1000), is the following:
In this case, both Column01 and Column02 values (as a SingleRow) will be sent on the event (as it is specified on the event property configuration).
After the event is raised the driver will wait for a reply as confirmation (processingMode: "ContinueOnProcessingConfirmation"). To reply to an event we need to execute a command of type ConfirmationDataProcessing. If no reply is received within the time configured (processingTimeout: 3000), the event will be sent again (up to the number defined as maxRetries). After that the event data will be lost and the polling process will start again.
Considering that the ignoreInitialValues is set as false, an event will be immediately triggered if there are values in the respective table.
Result example:
Example 3: Subscribe to a FIELD event
Event Configuration:
table: [Table01], argument: "Column01", pollingInterval: 1000, triggerType: "OnNewRows", trigger: "Field", resultDataFormat: "SingleRow", orderByColumn: "Column01", orderByType: "DESC", processingMode: "FireAndForget", ignoreInitialValues: true
Event Properties Configuration:
name: "EventPropName01", deviceId: "EventPropID01", columnName: "Column01"
name: "EventPropName02", deviceId: "EventPropID02", columnName: "Column02"
In this example the trigger query, which will be executed every second (pollingInterval: 1000), is the following:
In this case, both Column01 and Column02 values (as a SingleRow) will be sent on the event (as it is specified on the event property configuration).
Result example:
Command#
Commands are SQL queries which will be executed on a data base.
| Name | Type | Possible Values | Default Value | Description |
|---|---|---|---|---|
| type | Enum | Select Update Insert Delete Execute Raw ConfirmationDataProcessing | Select | Type of the command:Select : to execute a Select queryUpdate: to execute an Update queryInsert: to execute an Insert queryDelete: to execute a Delete queryExecute: to execute a Store ProcedureRaw: to execute a raw queryConfirmationDataProcessing: to confirm that an event was received (for the events with the processingMode set as ContinueOnProcessingConfirmation) |
| argument | String | Inform the system about necessary context for the command. For example, the Table Name or the Stored Procedure Name. | ||
| operation | Enum | AND OR None | AND | Type of operation to perform between ParameterQueries, applies to conditions (namely WHERE conditions) 'AND': Will perform an AND operation 'OR': Will perform an OR operation 'NONE': System will assume no operation. |
| resultType | Enum | ArrayOfResults SingleResult SingleValue | ArrayOfResults | Type of return that is expected for the command. 'ArrayOfResults': The system will return an array of objects, those objects will have a match between column names and values 'SingleResult': The system will return an object with a match between column names and values'SingleValue': The system will return the result of the query. |
Command Parameters#
A command parameter represents an inputs to a command and can be configured according to the following information:
| Name | Type | Possible Values | Default Value | Description |
|---|---|---|---|---|
| type | Enum | ParameterValue ParameterQuery RawQuery EventReply | ParameterValue | Type of the parameter in a query context:ParameterValue: columns to retrieve for command type Select, columns to update for command type Update or columns to insert for command type InsertParameterQuery: query filtering columns (command types Select, Update, Delete, Execute orRaw))RawQuery: raw query to be executed (command type Raw)EventReply: parameter that contains the event name (command type ConfirmationDataProcessing) |
| columnName | String | Relates for this command the parameter with the column in the command. | ||
| operation | Enum | Equal GreaterThan LessThan GreaterThanOrEqual LessThanOrEqualTo ALL ANY IN LIKE NOT | Equal | Type of operation to perform in command parameters of type ParameterQueries (will be ignored for other types) 'Equal': Will perform an = operation 'GreaterThan': Will perform an > operation 'LessThan': Will perform an < operation 'GreaterThanOrEqualTo': Will perform a >= operation 'LessThanOrEqualTo': Will perform a <= operation 'NotEqualTo': Will perform a <> operation. 'ALL': Will perform an ALL operation. 'ANY': Will perform an ANY operation. 'IN': Will perform an IN operation. 'LIKE': Will perform a LIKE operation. 'NOT': Will perform a NOT operation. 'None': Will not add any operation. |
Remarks/ Behavior#
-
If the command type is
Selectand no parameterValue is defined, all the columns will be retrieved. -
For the command type
Selectit is possible to use functions (likeCOUNT(),ROW_NUMBER()),MAX(), etc.). In that case it is necessary to set the function on the columnName for a specific parameterValue.- Example: If we set the columnName to
Count(column01) as Quantity, the query would beSelect Count(column01) as Quantity From table01
- Example: If we set the columnName to
-
ParameterValuehas a default value which will be used when no other value is provided to the command.
Command Examples#
Example 1: Execute a Select Command
Command Configuration:
type: "Select" , argument: "[Table01]", operation: "None", resultType: "ArrayOfResults"
Command Parameters Configuration:
name: "ParamValue", type: "ParameterValue", columnName: "Column01", operation: "None"
name: "ParamQuery", type: "ParameterQuery", columnName: "Column02", operation: "Equal"
When the command is executed, a value for the parameterQuery must be provided (10 in this example), and the query that will be executed is presented below:
As the command resultType is defined as ArrayOfResults, the result of the query will be returned as an array:
Example 2: Execute an Update Command
Command Configuration:
type: "Update" , argument: "[Table01]", operation: "AND", resultType: "SingleRow"
Command Parameters Configuration:
name: "ParamValue01", type: "ParameterValue", columnName: "Column01", operation: "None"
name: "ParamQuery01", type: "ParameterQuery", columnName: "Column01", operation: "Equal"
name: "ParamQuery02", type: "ParameterQuery", columnName: "Column02", operation: "GreaterThanOrEqualTo"
In this case we would need to provide all the 3 parameters upon the command execution. Assuming the values as ParamValue01 = false, ParamQuery01 = true, ParamQuery02 = 20, we would have the following query to be executed:
Driver Extensions#
This protocol driver provides a set of extension that allow the customization to perform actions that are independent of the Driver Definitions associated. This means you can, using customization, execute a command or even register/listen to an event without needing to describe them.
- This is particularly useful when accessing equipment data that is shared/too complex to access using the regular mechanisms. Also useful when needing to access data whose naming convention may vary from device to device.
- To use these extensions you can either implement your own task or use the supplied Tasks
Send Notification to DriverandSubscribe in Driver.
Objects#
The objects are structures that are passed as parameters.
Event#
| Name | Type | Description |
|---|---|---|
| name | String | Name of the event. Will be used as identifiers in the result calls. |
| isEnabled | Boolean | Is the event enabled and ready to be used? Default false |
| properties | Property[] | List of properties to link with the event |
Property#
| Name | Type | Description |
|---|---|---|
| name | String | Name of the property. Will be used as identifiers in the result calls. |
| deviceId | String | Unique identifier |
| deviceType | String | Data Type as the Server known the Property. Must use one from the supported Data Types of this protocol driver. |
| dataType | String | Data Type of the value as known/used by the MES/System. |
RegisterHandler#
| Name | Type | Description |
|---|---|---|
| event | Event | Event to register (full information) |
UnregisterHandler#
| Name | Type | Description |
|---|---|---|
| event | Event | Event to unregister (at least the property name must be supplied) |
Methods#
Register Event#
Notifies the protocol driver to raise the occurrences of a specific event when it occurs.
void connect.iot.driver.database.registerEvent(data: RegisterHandler)
![note] The events will be published to the listeners connect.iot.driver.database.event appended with the name of the event. Example: connect.iot.driver.database.event.CustomEvent
Example#
{
type:"connect.iot.driver.database.registerEvent",
content: {
name: "CustomEvent",
isEnabled: true,
extendedData: {
table: tableName,
argument: "ColumnName",
pollingInterval: 1000,
triggerType: "OnNewRows",
trigger: "RowNumber",
resultDataFormat: "AllNew",
processingTimeout: 3000,
maxRetries: 3,
maxRowsToProcess: 2,
orderByColumn: "ColumnName",
orderByType: "DESC",
processingMode: "FireAndForget",
ignoreInitialValues: true,
rawResultQuery: ""
},
properties: {
name: "PropertyName",
deviceId: "PropertyID",
dataType: "String",
deviceType: "NVARCHAR",
extendedData: {
columnName: "ColumnName"
}
}
}
}
Unregister Event#
Notifies the protocol driver to stop raising the occurrences of a specific event when they occur.
void connect.iot.driver.database.unregisterEvent(data: UnregisterHandler)
Example#
Send Command#
Sends a command to the driver to be executed
void connect.iot.driver.database.executeCommand(data: ExecuteCommandHandler)
Example#
{
type: "connect.iot.driver.database.executeCommand",
content: {
command: {
name: "SelectCustomCommand",
deviceId: "SelectCustomCommandID",
extendedData: {
type: "Select",
argument: "Table01",
operation: "None",
resultType: "ArrayOfResults"
},
parameters: [
{
name: "ParamName", deviceId: "ParamID", dataType: "String", deviceType: "NVARCHAR", extendedData: { type: "ParameterValue", columnName: "ColumnName", operation: "None" }
}
]
},
parameters: { "ParamName": "Value"}
}
}