Custom Communication Protocol API
Custom communication scripting can be activated by a boolean VT entry that can be accessed in the DataMan Setup Tool.
The methods are encapsulated in a communication object. Each communication channel creates an instance of the communication object.
When the Custom Protocol Communication API is enabled through a private DMCC command, the scripting context adds the following capabilities and requirements:
- The constructor function of the communication object, CommHandler, contains a list of functions that the script must contain:
- onConnect
- onDisconnect
- onExpectedData
- onTimer
- onUnexpectedData
- onError
- onEncoder
The user must implement these functions, as the custom communications function will call them.
- There are five member functions that the reader script engine offers, implemented by the reader:
- send
- close
- setTimer
- expectFramed
- setEncoder
By using these functions, a user could write javascript code that allows the reader to interact with another system. In particular, the user can write code to send messages back to the other system, something that is not supported in basic scripting.
Advantage
The script engine uses the same context for function execution and object creation. This allows the sharing of data between the script-based formatting and the custom communication scripts using global accessible objects.
List of functions
The communication member functions define the following method prototypes to be implemented by the user:
CommHandler – The constructor function for the communication object. The constructor must return a new communication handler object implementing the user methods in the communication script. The reader methods are added to the communication handler object directly after construction. The implementation of the constructor is mandatory and an error will be thrown if it does not exist. Since software version 5.5 the constructor function call offers the following argument:
- localName: The local name of the connection. The local name of a network connection is ”<READER_IP>:<PORT>”. An example for a Telnet connection is “10.82.80.156:23” with the default telnet port of 23. An example for a Network Client connection is “10.82.80.156:57350”. The local name for the serial connection is “COM1” or “COM USB”.
- onConnect – Initialize state upon connection (a network connection established or protocol stack starts on serial connection). If the method is not implemented an error occurs. The method has one argument and a return value:
- peerName – The peer name of the connection. The peer name for a network connection is ”<PEER_IP>:<PORT>”. An example peer name for a Telnet connection is “10.82.80.71:19772”, for a “Network Client” connection it is “10.82.80.71:1000”, where the host port is configured to 1000. The peer name for the serial connection is “COM1” or “COM USB”.
- return – The boolean return value defines if the handler for this connection should be activated:
- true: Enables customization of the communication protocol. Therefore, if you want to use your own protocol for communicating with the Dataman device, return true.
- false: If you do not need the customized protocol for this peer, return false.
- onDisconnect – Cleanup method called when closing the connection channel
- onExpectedData – Method called if data matching the set properties has arrived. The method has one argument:
- inputString – The received frame matched data excluding header and termination
- return – Determines if the data should be removed from input buffer
- true: clear the buffer.
- false: keep the value in buffer.
- onTimer – The timer value expired
- onUnexpectedData – The recieved data is not matching the requirements. The boolean return value determines if the data should be removed from input. The method has one argument:
- inputString – The received data
- return – Determines if the data should be removed from input buffer
- true: clear the buffer.
- false: keep the value in buffer.
- onError – An error occurred in the firmware and can be reported. The implementation of the method is mandatory. The method has one argument and no return value:
- errorMsg – The error message for trigger overruns (“Trigger Overrun”), buffer overruns (“Buffer Overflow”) and general errors reported by the firmware.
- onEncoder – Executed if a configured encoder distance is reached. The distance can be configured by the setEncoder method. The method has no arguments or return value.
- send – Send data to channel, returns the number of send characters. The method must be called with one argument:
- Data argument is a string
- close – Actively terminates connection for the communication object (for example, close TCP/IP socket). On UART, this causes onConnect to be called right afterwards.
- setTimer – Set the one-shot timer value when the onTimer will be executed. The timer can be re-initialized and aborted.
- Timeout in seconds of type double, internal resolution is us (1e-6 sec). A zero value aborts a running timer. Active timer will be overwritten.
- expectFramed – Tells the communication listener which data to pass on to the onExpectedData and onUnexpectedData methods. It is possible to change the match parameter at runtime. The following three arguments are required:
- header of type string, can be empty (””)
- terminator of type string, can be empty (””)
- max length of type integer, specifies the maximum length of an input message to check for a match [required]
- setEncoder – Units of the distance argument are millimetres. The encoder is configured in Setup Tool under System Settings -> Pulse Encoder. If encoder ticks should be used instead of distance set the value of the parameter “Resolution (mm)” to 1.
- distance (double) – The encoder distance in which the onEncoder method will be called.
The methods must be implemented in the public section of the object.
Examples
API usage of custom communication protocol object
This example below demonstrates the API usage of the custom communication protocol object. The example implements custom commands read from the connection. The commands are framed by a ”#” header and terminated by ”;\r” (for example, a serial PuTTY connection). A timer periodically sends timer messages. Use the custom stop command to stop them. You can change the timer handler once by the switch command.
|
function CommHandler() {
|
|
Generic use case: Heartbeat
Send out a periodic heartbeat message if reader is idle.
|
// Data Formatting:
var comm_handler = new Array(0);
// Converts read data to all upper case. Single code only. function onResult (decodeResults, readerProperties, output) {
}
// Communication:
// Heart beat example without disturbing the DMCC communication function CommHandler() {
|
} |
Generic use case: Real time timestamp
Implements a custom DMCC command to set the real time (send current time in seconds starting Jan 1 1970, as output by date +”%s” command). Prepend output with real time timestamp.
|
// communication script var time_offset=0;
function CommHandler() {
|
}
// data formatting script function onResult (decodeResults, readerProperties, output) {
} |
Customer Protocols implemented in various CR releases
Communication with cmf400 Profibus gateway
|
var CMF400_PROTOCOL_STATUS = {
}; // make the enum non-modifyable Object.freeze(CMF400_PROTOCOL_STATUS);
var cmf400_protocol_stx = '\x02'; // header var cmf400_protocol_etx = '\x03'; // termination
// VT Parameter to be converted into script configuration constant values: // "/Communication/Interfaces/COM1/Protocol") var vt_param_comif_com1_protocol = 1; // "/Communication/Protocols/CMF400/Profibus node number"), 3); var vt_param_profibus_node_number = 1; // "/Communication/Protocols/CMF400/Profibus mode"), 3);*/ var vt_param_profibus_mode = 1;
// TODO: how to configure parameter, where to store them with a out of stock firmware? var cmf400_protocol_profibus_node_number = 1;
var cmf400_protocol_profibus_mode = 1;
var cmf400_protocol_test_diagnostic_enabled = 0;
var cmf400_protocol_test_diagnostic = 'TEST';
// Protocol strings var cmf400_gateway_init = '+Gateway-Init+'; var cmf400_gateway_ident_ok = '+GW SOK TSICDPS'; var cmf400_gateway_ident_no = '+GW SNO TSICDPS'; var cmf400_gateway_run = '+GW-RUN+'; var cmf400_gateway_error = '+GW-ERR';
|
|
// Formatting helper function function zero_prefix(num, size) {
}
function CommHandler() {
|
} |
|
function onResult (decodeResults, readerProperties, output) {
} |
Pass weight string input along with decode string
|
// the constructor:
var input_string = "";
function CommHandler() {
}
|
|
//Empty data formatting entry point function function onResult (decodeResults, readerProperties, output) {
} |
FMPCS protocol
|
// This must be in the global scope, otherwise, it is undefined var bConnected = false;
dmccSet('TRIGGER.TYPE', 0); dmccSet('SYMBOL.4STATE-IMB', 1); dmccSet('SYMBOL.DATAMATRIX', 1); dmccSet('SYMBOL.I2O5', 1); dmccSet('SYMBOL.PDF417', 1); dmccSet('SYMBOL.POSTNET', 1);
function CommHandler() {
|
|
}; } |
The data formatting formats the result based on global variables set by the communication handler:
|
var packageID = "000000000"; // reset the package id var mode = 'a'; var lengthLimit = 9999;
function getFixedPsocId(id_) {
|
} function onResult (decodeResults, readerProperties, output) {
|
} |
Input match string, output from script (30x)
|
function CommHandler() {
|
}; } |
Data formatting delegates output to communication handler objects
|
var comm_handler = new Array(0);
// Converts read data to all upper case. Single code only. function onResult (decodeResults, readerProperties, output) {
} |
|
// Parameter: var system_id = '\x43'; // the system ID var heartbeat_time_s = 5.0; // heartbeat timer in sec [0-50] (0 is disabled) var append_crlf = true; // wether to
function CommHandler() {
|
|
this.sendErrorTelegram(errorCodes.index_in_use);
},
|
}; } |
Event Callback
The callback mechanism allows to register handler for trigger and input events. Handler for these events can be registered by the registerHandler method:
| callback_handle registerHandler(eventid, callback, ...) |
The registerHandler function requires the following arguments:
- eventid – identifier for the event type to register for
- callback – function object to execute on event
Available events identifier are defined in a constant object named “Callback”. Optional arguments can be used to configure the event, e.g. to filter the sensitivity.
A handle is returned that must be used to de-register the callback. To de-register the handler use the deregisterHandler function:
| deregisterHandler(callback_handle) |
- callback_handle – handle returned by the registerHandler method.
It is possible to register the callback handler within the global scope, e.g. to be used in data formatting.
Event Types
Current available events that can be registered are “onInput” and “onTrigger” events.
onInput event: It calls the callback function on input signal and button changes. The optional third argument allows to set filter for certain inputs. The object “ConstInput” defines masks for inputs:
- Input0:
- Input1:
- Input2:
- Input3:
- Input4:
- Input5:
- Input6:
- InputAll
- BnTrig
- BnTune
The input mask can be combined. The input values are sampled with an accuracy of 1 ms. The callback function for the onInput event has one argument for the new state of the input.
onTrigger event: It executes the callback function on trigger start and trigger end events. The callback function for the onTrigger event has two arguments: The first argument is the trigger object, the second argument the boolean state of the trigger, true for a trigger start and false for a trigger end.
Examples
The example defines three event handler:
- onInput0 – reacting on input0 signal and the switch button
- onInput1 – reacting on input1 signal
- onTrigger – reacting on trigger events
|
function CommHandler() {
|
}; } |
With the following event sequence: input1 on, input0 on, input0 off, input1 off, software trigger, switch on, switch off, we get the following output on the terminal:
|
call onInput1 for 'COM1, inputs=2 call onTrigger: start trigger with index 9 call onInput0 for 'COM1, inputs=1 call onTrigger: end trigger with index 9 call onInput0 for 'COM1, inputs=0 NO-READ call onInput1 for 'COM1, inputs=0 call onTrigger: start trigger with index 10 NO-READ call onTrigger: end trigger with index 10 call onInput0 for 'COM1, inputs=4096 call onTrigger: start trigger with index 11 call onInput0 for 'COM1, inputs=0 call onTrigger: end trigger with index 11 NO-READ |
The following example registers a handler on Input1 events and stores the state in a global variable. The state of the input is output by the data formatting.
|
var ginputs = false;
registerHandler(Callback.onInput, onInput, ConstInput.Input1);
// Default script for data formatting function onResult (decodeResults, readerProperties, output) {
}
function onInput(inputs) {
} |