Data Analytics NodeJS Guide¶
Overview¶
The Data Analytics functionality can be implemented as a Node.js script using the Node.js ZIOTC (Zebra IOT Connector) module resident on the reader.
The Node.js ZIOTC module is meant to abstract the underlying connections between the IoT Connector components (i.e. Radio Control and Reader Gateway) and allow the script to filter, analyze, and act on the data itself.
The minimal flow of the script would be:
Define callback functions
New Message Callback: Operates on the incoming data. This function will be called whenever there is new data to be filtered.
const onNewMessageCallback = (msg) => { ... };
For more details see New Message Callback
Passthru: Callback called when a new passthru message has been received from the reader gateway.
const onPassthruCallback = (msg) => { ... };
For more details see DA Passthru
OK: Callback called when the module ends
const onOKCallback = (msg) => { ... };
error: Callback called when the module encounters an error
const onNewErrorCallback = (msg) => { ... };
Open the ZIOTC module.
This will establish connections between the script and the other IoT Connector components.
const ziotc = require('./ziotc.node');
Set Data Source.
This will set the data source for incoming messages. The data source is set to CONNECT_FOR_RADIO_DATA by default. Refer to NodeJS API reference Guide for further details.
ziotc.SetDataSource("CONNECT_FOR_RADIO_DATA");
Register callbacks and Run ZIOTC
This will register the previously defined callback functions and run the module.
ziotc.Run(onErrorCallback, onOkCallback, onNewMessageCallback, onPassthruCallback);
New Message Callback¶
The user-defined new message callback function is the core of the script. The new message callback will be called each time a new message arrives.The message will be an object containing a “type” field (input message type) and a “msg” field (actual message). The function can then process the message.
For example, the following callback function, sends out a data message if the tag’s ID begins with a prefix.
var prefix = "00"; const onNewMessageCallback = (msg) => { if ( msg["type"] == ziotc.MSG_IN_JSON ) { tag_id_hex = JSON.parse(msg["msg"])["data"]["idHex"] if (tag_id_hex.startsWith(prefix)) { msg["type"]=ziotc.MSG_OUT_DATA; ziotc.SendNextMsg(msg); } } };
Input Message types¶
The new message callback will be called each time a new message arrives.The message will be an object containing a “type” field (input message type) and a “msg” field (actual message).
The currently available values for incoming messages types are:
MSG_IN_JSON =0 MSG_IN_GPI = 6
The MSG_IN_JSON type states that the incoming message is a JSON tag information message. The format of the message is identical to the format of tag messages coming directly from the Radio Control. When the message type is MSG_IN_JSON, msg field contains a JSON string that can be parsed into an object. The MSG_IN_GPI type states that the incoming message is a JSON GPI event message. The format is identical to the format of GPI messages defined here.
Output Message types¶
Messages can be sent to the Reader Gateway and off the reader by calling:
ziotc.SendNextMsg(message);
where message is an object having a “type” field (output message type) and a “msg” field (actual message).
var message = { type: ziotc.MSG_OUT_GPO , msg: JSON.stringify({type:"GPO",state:"HIGH",pin:1}) };
The currently available values for the output message types are:
MSG_TYPE_DATA = 3 MSG_TYPE_CTRL = 4 MSG_TYPE_GPO = 5
The MSG_TYPE_DATA type will send the message to the Reader Gateway to output on the Data Interface. The MSG_TYPE_CTRL type will send the message to the Reader Gateway to output on the Management Event Interface. The MSG_TYPE_GPO type will send the message to the GPIO-LED module.
Data Analytics Passthru¶
In addition to processing data from the Radio Control and passing new, or filtered, data through to the Reader Gateway, messages can be passed through the Reader Gateway directly to the Data Analytics script. These messages can be sent to the Reader Gateway via the Management Command/Response interface.
In order to process the pass through messages, a pass through callback must be defined and registered with the ZIOTC object. The pass through callback takes in a single parameter - the pass through message. The function MUST issue a sendResponse with a message. This functionality enables a mechanism to configure the Data Analytics Script. The following code snippet continues the example above and allows for a single command “prefix” to be sent to the script. If only “prefix” is sent, the script returns the current value the script is using to filter tags. If prefix is followed by another string, it will update the “prefix” to the new value.
const onPassthruCallback = (msg) =>{ try { if (msg.startsWith("prefix")) { parts = msg.split(" ") if (parts.length >= 2) { prefix = parts[1] } ziotc.SendResponse("prefix set to " + prefix); } else { ziotc.SendResponse("unrecognized command"); } catch(err) { console.log(err.message); } };
Management and Control of Reader¶
DA apps can manage and control the reader using the REST interface described here. Reader bundles the nodejs http
module which can be used to call local rest apis.
const http = require('http');
const options = {
hostname: '127.0.0.1',
port: 80,
path: '/cloud/status',
method: 'GET',
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Request successful!');
console.log('Response data:', data);
});
});
req.on('error', (error) => {
console.error('Request failed. Error:', error.message);
});
req.end();
GPI event Notification¶
The process of GPI event notification can be accomplished through the utilization of the EnableGPIEvents function.The DA app can use the EnableGPIEvents function to register for GPI event notification.Thus whenever GPI events occur the OnNewMessageCallback is called with the message objects ‘type’ field set to MSG_IN_GPI and the ‘msg’ field containing the details of the GPI event.The following is a sample code for GPI event notification
const ziotc = require('ziotc.node');
const onNewMessageCallback = (msg) => {
if ( msg["type"] == ziotc.MSG_IN_GPI ){
console.log("GPI event received %s",msg["msg"]);
}
};
ziotc.Run(onErrorCallback, onOkCallback, onNewMessageCallback, onPassthruCallback);
ziotc.EnableGPIEvents();
Controlling GPO and LED¶
DA apps can control the reader’s GPOs and LEDs using the SendNextMsg
method.
LED can be controlled by sending the below payload in SendNextMsg
method.
{type:"LED",led:3,color:"GREEN"}
Note
Only the App LED (LED 3) can be controlled by the user app.
The sample below changes the color of the LED periodically.
const {execSync} = require('child_process'); var led_green_msg = { type: ziotc.MSG_OUT_GPO , msg: JSON.stringify({type:"LED",led:3,color:"GREEN"}) }; var led_yellow_msg = { type: ziotc.MSG_OUT_GPO , msg: JSON.stringify({type:"LED",led:3,color:"AMBER"}) }; var led_red_msg = { type: ziotc.MSG_OUT_GPO , msg: JSON.stringify({type:"LED",led:3,color:"RED"}) }; while(true){ execSync('sleep 1'); ziotc.SendNextMsg(led_green_msg); execSync('sleep 1'); ziotc.SendNextMsg(led_yellow_msg); execSync('sleep 1'); ziotc.SendNextMsg(led_red_msg); }
Controlling GPO can be achieved by sending the below json object in the payload for SendNextMsg
method.
{"type":"GPO","state":"HIGH","pin":1}
The sample below toggles the GPO periodically.
const {execSync} = require('child_process');
var gpo_high_msg = {
type: ziotc.MSG_OUT_GPO ,
msg: JSON.stringify({type:"GPO",state:"HIGH",pin:1})
};
var gpo_low_msg = {
type: ziotc.MSG_OUT_GPO ,
msg: JSON.stringify({type:"GPO",state:"LOW",pin:1})
};
while(true){
execSync('sleep 1');
ziotc.SendNextMsg(gpo_high_msg);
execSync('sleep 1');
ziotc.SendNextMsg(gpo_low_msg);
}
Sending Asynchronous messages from the DA app¶
DA apps can also send asynchronous messages via the management events endpoint of the IoT Connector
. The sample below illustrates sendinga sample message from the DA app.
var sample_async_msg = {
type: ziotc.MSG_OUT_CTRL ,
msg: JSON.stringify({source:"Sample DA app",message:"Sample message from DA app"})
};
ziotc.SendNextMsg(sample_async_msg);
Full NodeJS script¶
Below is a sample script based on the code snippets above.
const ziotc = require('ziotc.node'); const onErrorCallback = (msg) => { console.log(msg); }; const onOkCallback = () => { console.log("done"); }; var prefix = "00"; const onNewMessageCallback = (msg) => { if ( msg["type"] == 0 ) { tag_id_hex = JSON.parse(msg["msg"])["data"]["idHex"] if (tag_id_hex.startsWith(prefix)) { msg["type"]=ziotc.MSG_OUT_DATA; ziotc.SendNextMsg(msg); } } }; const onPassthruCallback = (msg) =>{ try { if (msg.startsWith("prefix")) { parts = msg.split(" ") if (parts.length >= 2) { prefix = parts[1] } ziotc.SendResponse("prefix set to " + prefix); } else ziotc.SendResponse("unrecognized command"); } catch(err) { console.log(err.message); } }; ziotc.SetDataSource("CONNECT_FOR_RADIO_DATA"); ziotc.Run(onErrorCallback, onOkCallback, onNewMessageCallback, onPassthruCallback); console.log("started DA simple application") function stopZIOTC() { console.log(`stopping...`); ziotc.Stop(); } setTimeout(stopZIOTC, 60000); // run for 1 minute