Data Analytics Python Guide¶
The Data Analytics functionality can be implemented as a Python script using the Python pyziotc
(Zebra IOT Connector) module resident on the reader.
The Python pyziotc 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 is as follows:
Define a new message callback function to operate on the incoming data. This function will be called whenever there is new data to be filtered.
def new_msg_callback(msg_type, msg_in): pass
For more details see New Message Callback
Open the pyziotc module. This will extablish connections between the script and the other IoT Connector components.
import pyziotc ziotcObject = pyziotc.Ziotc()
Register the previously defined function from step 1. This notifies the pyziotc module to use the callback funtion when new messages arrive.
ziotcObject.reg_new_msg_callback(new_msg_callback)
Note
The loop.run_forever() method that was required to be called in the legacy python module is not required anymore.
New Message Callback¶
The user-defined new message callback function is the core of the script. The callback definition must contain 2 parameters, msg_type and msg_in. The function can then process the input message and send out an output message based on the input. All messages shall be Python bytearrays
For example, the following callback function, only sends out a data message if the beginning of the tag’s ID begins with a prefix.
prefix = '38' def new_msg_callback(msg_type, msg_in): if msg_type == pyziotc.MSG_IN_JSON: msg_in_json = json.loads(msg_in) tag_id_hex = msg_in_json["data"]["idHex"] if tag_id_hex.startswith(prefix): z.send_next_msg(pyziotc.MSG_OUT_DATA, bytearray("Filtered data " + msg_in, 'utf-8'))
Input Message types¶
The new message callback will be called each time a new message arrives from the Radio Control. The incoming msg_type is a constant defined in the ziotc.py module. The currently available value for incoming messages is:
MSG_IN_JSON = 0 MSG_IN_GPI = 6
The MSG_IN_JSON type is a JSON tag information message (after decoding from the bytearray). The format is identical to the format of tag messages coming directly from the Radio Control. The MSG_IN_GPI type is a JSON GPI event message (after decoding from the bytearray). 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:
ziotcObject.send_next_msg(msg_type, msg_out)
msg_type is a constant defined in the ziotc.py module. The currently available value for outgoing messages are:
MSG_OUT_DATA= 3 MSG_OUT_CTRL= 4 MSG_OUT_GPO = 5
The MSG_OUT_DATA type will send the message to the Reader Gateway to output on the Data Interface. The MSG_OUT_CTRL type will send the message to the Reader Gateway to output on the Management Event Interface. The MSG_OUT_GPO type will send the control the GPO/LED.
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 passed through messages, a pass through callback must be defined and registered with the ZIOTC object.
The pass through callback takes in a single parameter. It is a bytearray of the incoming message.
Important
The function must return a response message that is also a bytearray.
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.
def passthru_callback(msg_in): global prefix parts = msg_in.split(" ") print(parts) if parts[0] == "prefix": if len(parts) == 1: response = "prefix set to {}".format(prefix) response = bytearray(response, 'utf-8') else: prefix = parts[1] response = "prefix set to {}".format(prefix) response = bytearray(response, 'utf-8') else: response = b"unrecognized command" return response ziotcObject.reg_pass_through_callback(passthru_callback)
Management and Control of Reader¶
DA apps can manage and control the reader using the REST interface described here. Reader bundles the python http
module which can be used to call local rest apis.
import http.client
from http.client import HTTPConnection
c=HTTPConnection("127.0.0.1")
c.request('GET', '/cloud/status')
res = c.getresponse()
data = res.read()
print(data)
Notifying GPI events¶
The process of notifying gpi events can be accomplished through the utilization of the enableGPIEvents function.The following is an example app that is displayed below.
import pyziotc
import json
def new_msg_callback(msg_type, msg_in):
if msg_type == pyziotc.MSG_IN_GPI:
print("GPI events : ", msg_in)
z = pyziotc.Ziotc()
z.enableGPIEvents()
z.reg_new_msg_callback(new_msg_callback)
Controlling GPO and LED¶
DA apps can control the reader GPOs and LEDs using the send_next_msg
method.
LED can be controlled by sending the below payload in send_next_msg
method.
{"type":"LED","color":"RED","LED":3}
Note
Only the App LED (LED 3) can be controlled by the user app.
The sample below changes the color of the LED preiodically.
import pyziotc
import json
import time
led_green_msg = bytearray(json.dumps({"type":"LED","color":"GREEN","led":3}), "utf-8")
led_yellow_msg = bytearray(json.dumps({"type":"LED","color":"AMBER","led":3}), "utf-8")
led_red_msg = bytearray(json.dumps({"type":"LED","color":"RED","led":3}), "utf-8")
z = pyziotc.Ziotc()
while True:
time.sleep(1)
z.send_next_msg(pyziotc.MSG_OUT_GPO, led_green_msg)
time.sleep(1)
z.send_next_msg(pyziotc.MSG_OUT_GPO, led_red_msg)
time.sleep(1)
z.send_next_msg(pyziotc.MSG_OUT_GPO, led_yellow_msg)
Controlling GPO can be achieved by sending the below json object in the payload for send_next_msg
method.
{"type":"GPO","state":"HIGH","pin":1}
The sample below toggles the GPO preiodically.
import pyziotc
import json
import time
gpo_high_msg = bytearray(json.dumps({"type":"GPO","state":"HIGH","pin":1}), "utf-8")
gpo_low_msg = bytearray(json.dumps({"type":"GPO","state":"LOW","pin":1}), "utf-8")
z = pyziotc.Ziotc()
while True:
time.sleep(1)
z.send_next_msg(pyziotc.MSG_OUT_GPO, gpo_high_msg)
time.sleep(1)
z.send_next_msg(pyziotc.MSG_OUT_GPO, 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 sending version message at startup.
import pyziotc
import json
import time
version_msg = bytearray(json.dumps({"version": 1, "time": time.now()}), "utf-8")
z = pyziotc.Ziotc()
z.send_next_msg(pyziotc.MSG_OUT_CTRL,version_msg)
Sample Python DA app¶
Below is the sample DA app that filters data and controls the LED preiodically. It also sends and asynchronous message via the management events interface whenever the LED changes color.
example 1:
import pyziotc import json prefix = "43" def passthru_callback(msg_in): global prefix parts = msg_in.split(" ") print(parts) if parts[0] == "prefix": if len(parts) == 1: response = "prefix set to {}".format(prefix) response = bytearray(response, 'utf-8') else: prefix = parts[1] response = "prefix set to {}".format(prefix) response = bytearray(response, 'utf-8') else: response = b"unrecognized command" return response def new_msg_callback(msg_type, msg_in): if msg_type == ziotc.ZIOTC_MSG_TYPE_TAG_INFO_JSON: msg_in_json = json.loads(msg_in) tag_id_hex = msg_in_json["data"]["idHex"] if tag_id_hex.startswith(prefix): ziotcObject.send_next_msg(zitoc.ZIOTC_MSG_TYPE_DATA, bytearray(msg_in, 'utf-8')) ziotcObject = pyziotc.Ziotc() ziotcObject.reg_new_msg_callback(new_msg_callback) ziotcObject.reg_pass_through_callback(passthru_callback) led_green_msg = bytearray(json.dumps({"type":"LED","color":"GREEN","led":3}), "utf-8") led_yellow_msg = bytearray(json.dumps({"type":"LED","color":"AMBER","led":3}), "utf-8") led_red_msg = bytearray(json.dumps({"type":"LED","color":"RED","led":3}), "utf-8") # The below formats for async messages are for illustration only. it can be anything the app wants. async_msg_red = bytearray(json.dumps({"source":"Sample DA app","message":"LED set to RED"}), "utf-8") async_msg_green = bytearray(json.dumps({"source":"Sample DA app","message":"LED set to GREEN"}), "utf-8") async_msg_yellow = bytearray(json.dumps({"source":"Sample DA app","message":"LED set to YELLOW"}), "utf-8") while True: time.sleep(1) z.send_next_msg(pyziotc.MSG_OUT_GPO, led_green_msg) z.send_next_msg(pyziotc.MSG_OUT_CTRL, async_msg_green) time.sleep(1) z.send_next_msg(pyziotc.MSG_OUT_GPO, led_red_msg) z.send_next_msg(pyziotc.MSG_OUT_CTRL, async_msg_red) time.sleep(1) z.send_next_msg(pyziotc.MSG_OUT_GPO, led_yellow_msg) z.send_next_msg(pyziotc.MSG_OUT_CTRL, async_msg_yellow)