Linux SDK Sample Applications

Overview

This chapter describes how to use the Zebra Scanner SDK, and includes code snippets from the sample application.

NOTE For a list of a scanner's supported attribute (parameter) numbers and definitions, refer to the scanner Product Reference Guide, available on the Zebra Support website: http://www.zebra.com/support. Attributes include configuration parameters, monitored data, and asset tracking information.


SDK Sample Utilities

The Zebra Scanner SDK includes the following sample utilities that demonstrate SDK functionalities. This section describes how to use the utilities to gain an understanding of the SDK.

Developing a Console Application Using zebra-scanner-devel and Libraries

zebra-scanner-sdk main packages include a development package that contains header files to access CoreScanner API calls, as well as source code for a sample application. The sample application can be modified and compiled using the make file to create a new application. Include a path for header files and LD_FLAGS.

NOTE The sample application demonstrates how to develop an application for Zebra scanner drivers.

Table 1: Installation Locations for Sample Application, Development Resources, and Shared Libraries

Application Type Installation Location File
Sample application /usr/share/zebra-scanner/samples/co nsole-app Makefile
ConsoleApplication
/usr/share/zebra-scanner/samples/co nsole-app/include ConsoleSampleEventListener.h
ConsoleMain.h
/usr/share/zebra-scanner/samples/co nsole-app/src ConsoleSampleEventListener.cpp
ConsoleMain.cpp
Development files for uPOS applications, files are installed by zebra-scanner-devel package /usr/include/zebra-scanner CsBarcodeTypes.h
CsUserDefs.h
CsIEventListenerXml.h
Cslibcorescanner_xml.h
CoreScanner shared libraries /usr/lib/zebra-scanner/corescanner libcs-iudev.so.4.0.0
libcs-comm.so.4.0.0
libcs-common.so.4.0.0
libcscl-snapi.so.4.0.0
libcs-client.so.4.0.0
libcs-clientscanner.so.4.0.0
libcs-clientscale.so.4.0.0
libcscl-ibmtt.so.4.0.0
libcscl-ibmhh.so.4.0.0
libcscl-hidkb.so.4.0.0
libcs-client.so
libcs-clientscale.so
libcs-clientscanner.so
libcs-comm.so
libcs-common.so
libcs-iudev.so
libcscl-hidkb.so
libcscl-snapi.so
libcscl-ibmtt.so
libcscl-ibmhh.so

An application should extend the IEventListenerXml class from the zebra-scanner-devel package. IEventListenerXml is an abstract class with pure virtual functions for all event handling. The included sample application implements all event handling methods. Additional methods support required features, and each method calls the ExecCommand() method after preparing input XML.

For example, ConsoleSampleEventListener.h is implemented in the IEventListenerXml class of the Console Application.

A developer implements all pure abstract methods inside the sample application's class SampleEventListener, which is derived from the IEventListenerXML interface. The SampleEventListener class can then be instantiated inside the main method. The following API calls are used for further development:

  • Open
  • GetScanners
  • ExecCommand
  • Close

Source Code for the Console Application

Class SampleEventListener (ConsoleSampleEventListener.h)


/*
* ©2022 Zebra Technologies LLC. All rights reserved.
*/

#ifndef SAMPLEEVENTLISTENER_H_
#define SAMPLEEVENTLISTENER_H_

#include "CsIEventListenerXml.h"
#include "CsUserDefs.h"
#include "CsBarcodeTypes.h"
#include "Cslibcorescanner_xml.h"

/* standard C includes */
#include <stdio.h>
#include <stdlib.h>

/* standard template library includes */
#include <string>
#include <iostream>
#include <sstream>

using namespace std;

class SampleEventListener : public IEventListenerXml
{
public:
    explicit SampleEventListener();
    virtual ~SampleEventListener();

    virtual void OnImageEvent( short eventType, int size, short imageFormat, char* sfimageData, int dataLength, std::string& pScannerData );
    virtual void OnVideoEvent( short eventType, int size, char* sfvideoData, int dataLength, std::string& pScannerData );
    virtual void OnBarcodeEvent( short eventType, std::string& pscanData );
    virtual void OnPNPEvent( short eventType, std::string ppnpData );
    virtual void OnCommandResponseEvent( short status, std::string& prspData );
    virtual void OnScannerNotification( short notificationType, std::string& pScannerData );
    virtual void OnIOEvent( short type, unsigned char data );
    virtual void OnScanRMDEvent( short eventType, std::string& prmdData );
    virtual void OnDisconnect();
    virtual void OnBinaryDataEvent( short eventType, int size, short dataFormat, unsigned char* sfBinaryData, std::string&  pScannerData);


    StatusID Open();
    void GetScanners();
    void GetAttribute();
    void GetAttributeNext();
    void GetAllAttributes();
    void SetAttribute();
    void SetAttributeStore();
    void SetZeroWeight();
    void Close();
    
    void RebootScanner();
    void ExecuteActionCommand(CmdOpcode opCode);
    void GetDeviceTopology();
    void FirmwareUpdate();
    void FirmwareUpdateFromPlugin();
    void StartNewFirmware();
    void AbortFirmwareUpdate();
    void GetVersion();
    void SwitchHostMode();
};

#endif /* SAMPLEEVENTLISTENER_H_ */                                                           

Class SampleEventListener Definitions/Implementation (ConsoleSampleEventListener.cpp)


/*
* ©2022 Zebra Technologies LLC. All rights reserved.
*/

#include "ConsoleSampleEventListener.h"
#include "ISO15434formatEnvelope.h"

/* standard C includes */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/* standard template library includes */
#include <string>
#include <iostream>
#include <sstream>
#include <errno.h>
#include <cstring>
#include <time.h>

SampleEventListener::SampleEventListener()
{

}

SampleEventListener::~SampleEventListener()
{
    Close();
}

StatusID SampleEventListener::Open()
{
    StatusID status;
    ::Open(this, SCANNER_TYPE_ALL, &status);
    if(status != STATUS_OK)
    {
        return status;
    }

    std::string inXml = "<inArgs><cmdArgs><arg-int>6</arg-int><arg-int>1,2,4,8,16,32</arg-int></cmdArgs></inArgs>";
    std::string outXml;
    ::ExecCommand(CMD_REGISTER_FOR_EVENTS, inXml, outXml, &status);   
    return status;
}
   
void SampleEventListener::GetScanners()
{
    unsigned short count;
    vector<unsigned int> list;
    string outXml;
    StatusID eStatus;

    ::GetScanners(&count, &list, outXml, &eStatus);
    
    cout << "================================" << endl;

    if ( eStatus != STATUS_OK )
    {
        std::cout << "Get Scanners failed. Can't connect to the corescanner." << std::endl;
        return ;
    }

    cout << "Get Scanners command success. " << endl << endl;
    cout << "Scanner Count: " << count << endl;
    for(int x=0; x> scannerID;
    cout << "Enter attribute number or comma separated attribute numbers : " ;
    std::string attribute_number = "";
    cin >> attribute_number;

    std::string inXml = "<inArgs><scannerID>" + scannerID + 
                        "</scannerID><cmdArgs><arg-xml><attrib_list>" + 
                        attribute_number + "</attrib_list></arg-xml></cmdArgs></inArgs>";
            
    StatusID sId;
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl;
    ::ExecCommand(CMD_RSM_ATTR_GET, inXml, outXml, &sId);    
    
    cout << "================================" << endl;
    if(sId == STATUS_OK)
    {
        cout << "GetAttribute command success." << endl << endl;        
        cout << "Out XML : " << outXml << endl;
    }
    else
    {
        cout << "GetAttribute command failed. Error code : " << sId << endl;
    }
    cout << "================================" << endl<< endl;
}
   
void SampleEventListener::GetAttributeNext()
{
    std::string scannerID = "";
    cout << "Enter Scanner ID : " << endl;
    cin >> scannerID;
    cout << "Enter current attribute number : " ;
    std::string attribute_number = "";
    cin >> attribute_number;

    std::string inXml = "<inArgs><scannerID>" + scannerID + 
                        "</scannerID><cmdArgs><arg-xml><attrib_list>" + 
                        attribute_number + "</attrib_list></arg-xml></cmdArgs></inArgs>";    
    
    StatusID sId;
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl;
    ::ExecCommand(CMD_RSM_ATTR_GETNEXT, inXml, outXml, &sId);
    
    cout << "================================" << endl;
    
    if(sId == STATUS_OK)
    {
        cout << "GetAttributeNext command success. " << endl << endl;        
        cout << "Out XML : " << outXml << endl;
    }
    else
    {
        cout << "GetAttributeNext command failed. Error code : " << sId << endl;
    }
    
    cout << "================================" << endl << endl;
}
   
void SampleEventListener::GetAllAttributes()
{    
    std::string scannerID = "";     
    
    cout << "Enter scanner ID: ";
    cin >> scannerID;
    
    std::string inXml = "<inArgs><scannerID>"+scannerID+"</scannerID></inArgs>";
    StatusID sId;
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl;
    ::ExecCommand(CMD_RSM_ATTR_GETALL, inXml, outXml, &sId);
        
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "GetAllAttributes command success. " << endl << endl;        
        cout << "Out XML : " << outXml << endl;
    }
    else
    {
        cout << "GetAllAttributes command failed. Error code : " << sId << endl;
    }
    cout << "================================" << endl << endl;
}

void SampleEventListener::SetAttribute()
{
    std::string scannerID = "";
    cout << "Enter scanner ID : " << endl;
    cin >> scannerID;
    std::string attributeNumber = "";
    cout << "Enter attribute number : " << endl;
    cin >> attributeNumber;
    std::string dataType = "";
    cout << "Enter data type : " << endl;
    cin >> dataType;
    std::string attributeValue = "";
    cout << "Enter attribute value : " << endl;
    cin >> attributeValue;
    
    std::string inXml = "<inArgs><scannerID>"+ scannerID +
                        "</scannerID><cmdArgs><arg-xml><attrib_list><attribute><id>" + attributeNumber + 
                        "</id><datatype>" + dataType + 
                        "</datatype><value>" + attributeValue + 
                        "</value></attribute></attrib_list></arg-xml></cmdArgs></inArgs>";
    
    StatusID sId;    
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl;   
    ::ExecCommand(CMD_RSM_ATTR_SET, inXml, outXml, &sId);
    
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "SetAttribute command success. " << endl << endl;            
    }
    else
    {
        cout << "SetAttribute command failed. Error code : " << sId << endl;
    }
    
    cout << "================================" << endl << endl;

}
   
void SampleEventListener::SetAttributeStore()
{
    std::string scannerID = "";
    cout << "Enter scanner ID : " << endl;
    cin >> scannerID;
    std::string attributeNumber = "";
    cout << "Enter attribute number : " << endl;
    cin >> attributeNumber;
    std::string dataType = "";
    cout << "Enter data type : " << endl;
    cin >> dataType;
    std::string attributeValue = "";
    cout << "Enter attribute value : " << endl;
    cin >> attributeValue;    

    std::string inXml = "<inArgs><scannerID>"+ scannerID +
                        "</scannerID><cmdArgs><arg-xml><attrib_list><attribute><id>" + attributeNumber + 
                        "</id><datatype>" + dataType + 
                        "</datatype><value>" + attributeValue + 
                        "</value></attribute></attrib_list></arg-xml></cmdArgs></inArgs>";
    
    StatusID sId;    
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl; 
    ::ExecCommand(CMD_RSM_ATTR_STORE, inXml, outXml, &sId);
    
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "StoreAttribute command success. " << endl << endl;               
    }
    else
    {
        cout << "StoreAttribute command failed. Error code : " << sId << endl;
    }    
    cout << "================================" << endl << endl;
}
   
void SampleEventListener::SetZeroWeight()
{
    std::string inXml = "<inArgs><scannerID>1</scannerID><cmdArgs><arg-xml><attrib_list><attribute><id>6019</id><datatype>X</datatype><value>0</value></attribute></attrib_list></arg-xml></cmdArgs></inArgs>";

    StatusID sId;
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl;     
    ::ExecCommand(CMD_RSM_ATTR_SET, inXml, outXml, &sId);
        
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "SetZeroWeight command success. " << endl << endl;          
    }
    else
    {
        cout << "SetZeroWeight command failed. Error code : " << sId << endl;
    } 
    cout << "================================" << endl << endl;
}
   
//Event EventListener for get Get Version number of Core scanner
void SampleEventListener::GetVersion() {
    
    std::string inXml = "<inArgs></inArgs>";   
    StatusID sId;
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl;
    ::ExecCommand(CMD_GET_VERSION, inXml, outXml, &sId);
        
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "GetVersion command success. " << endl << endl;        
        cout << "Out XML : " << outXml << endl;
    }
    else
    {
        cout << "GetVersion command failed. Error code : " << sId << endl;
    } 
    cout << "================================" << endl << endl;    
}

void SampleEventListener::Close()
{
    StatusID status;
    ::Close(0, &status);

}
   
string getStringFromRawData(unsigned char* rawData,int startIndex, int endIndex)
{
    int numElements = endIndex-startIndex;
    char buffer [numElements];
    int j=0;
    for(int i=startIndex;i<endIndex;i++){
        sprintf (&buffer[j++], "%c", rawData[i]);
    }
    string str(buffer);
    return str;
}

void SampleEventListener::OnImageEvent( short eventType, int size, short imageFormat, char* sfimageData, int dataLength, std::string& pScannerData )
{
    cout << "OnImageEvent" << endl;
}
   
void SampleEventListener::OnBinaryDataEvent( short eventType, int size, short dataFormat, unsigned char* sfBinaryData, std::string&  pScannerData)
{    
    //Constants for ISO15434 messages
    const unsigned char ISO_RS = 0x1E;      // ISO15454 Format Trailer Character
    //const unsigned char ISO_GS = 0x1D;    // ISO15454 Data Element Separator
    const unsigned char ISO_EOT = 0x04;     // ISO15454 Message Trailer Character
    const unsigned char MSG_EASYCAP = 0;    // ISO15451 Message DocCap message number
    FILE *imgFile; 
    cout << "OnBinaryDataEvent" << endl;
        
    int packetLength = (sfBinaryData[0] << 24) |
                    (sfBinaryData[1] << 16) |
                    (sfBinaryData[2] << 8) |
                    sfBinaryData[3];
    
    if(packetLength+4!= size)
    {
        cout << "Incorrect packet size\n" << endl;
    }
    else
    {
        if(sfBinaryData[4]!= MSG_EASYCAP)
        {
            cout << "Incorrect Msg type\n" << endl;
        }
        else
        {
            // ISO15434 Envelope: is message header correct?
            if ((sfBinaryData[5] != '[') || (sfBinaryData[6] != ')') || (sfBinaryData[7] != '>') || (sfBinaryData[8] != ISO_RS))
            {
                cout << "Incorrect message header\n" << endl;
            }
            else
            {
                // ISO15434 Envelope: is message header correct?
                if (sfBinaryData[size - 1] != ISO_EOT)
                {
                    cout << "Incorrect message header ISO_EOT\n" << endl;
                }
                else
                {
                    cout << "Correct packet received \n" << endl;
                    ISO15434formatEnvelope *anEnvelope = new ISO15434formatEnvelope(sfBinaryData,size, 9);
                    while (anEnvelope->getNext())
                    {
                        string fileType = anEnvelope->getFileType();

                        if (fileType == "BarCode")
                        {
                            string decodeData=getStringFromRawData(sfBinaryData,anEnvelope->getDataIndex(),anEnvelope->getDataIndex()+anEnvelope->getDataLength());
                            cout << "Barcode received " << endl;
                            cout << " Data type = "<<  (int)decodeData.at(0) << endl;
                            cout << " Data = "<< decodeData.substr(1,anEnvelope->getDataLength())<< endl;
                        }
                        else
                        {
                            char filename[200];
                            string fileFormat = anEnvelope->getFileType();
                            time_t t = time(0);   // get time now
                            tm* now = localtime(&t);
                            sprintf(filename,"ZIMG-%d%d%d%d%d%d%s%s", now->tm_year + 1900, now->tm_mon + 1,now->tm_mday,now->tm_hour,now->tm_min,now->tm_sec,".",fileFormat.c_str());
                            imgFile = fopen(filename, "w");
                            if (!imgFile)
                            {
                                cout << "Unable to open file " << filename<< endl;
                                continue;
                            }
                            fwrite(&sfBinaryData[anEnvelope->getDataIndex()]+6,sizeof(unsigned char),anEnvelope->getDataLength()+6,imgFile);
                            fflush(imgFile);
                            fclose (imgFile);
                            cout << "ImageData saved in " <<filename<< endl;
                        }
                    }
                }
            }  
        }
    }
}
   
void SampleEventListener::OnVideoEvent( short eventType, int size, char* sfvideoData, int dataLength, std::string& pScannerData )
{
    cout << "OnVideoEvent" << endl;
}

void SampleEventListener::OnPNPEvent( short eventType, std::string ppnpData )
{
    string str;
    if (eventType == SCANNER_ATTACHED) {
        cout << "Scanner attached" << endl;
        str = ppnpData;
    } else if (eventType == SCANNER_DETACHED) {
        cout << "Scanner detached" << endl;
        str =  ppnpData;
    } else {
        str = " UNKNOWN PNP Event ";
    }
    cout << str << endl;
}

void SampleEventListener::OnCommandResponseEvent( short status, std::string& prspData )
{
    cout << endl << "Scanner data: " << prspData << endl;
    cout << "OnCommandResponseEvent" << endl;
    cout << prspData << endl;
}

void SampleEventListener::OnScannerNotification( short notificationType, std::string& pScannerData )
{
    cout << endl << "Scanner event data: " << pScannerData << endl;
    cout << "OnScannerNotification" << endl;
}

void SampleEventListener::OnIOEvent( short type, unsigned char data )
{
    cout << "OnIOEvent" << endl;
}
   
void SampleEventListener::OnScanRMDEvent( short eventType, std::string& prmdData )
{
    cout << "OnScanRMDEvent" << endl;
        cout << "Out XML " << endl;
        cout << prmdData << endl;
}

void SampleEventListener::OnDisconnect()
{
    cout << "OnDisconnect" << endl;
}

void SampleEventListener::OnBarcodeEvent(short int eventType, std::string & pscanData)
{
    cout << "Barcode Detected" << endl;
    cout << "Out XML" << endl;
    cout << pscanData << endl;
}

void SampleEventListener::RebootScanner()
{
    
}
   
void SampleEventListener::FirmwareUpdate()
{
    std::string inXml;
    std::string outXml;
    std::string datFilePath; 
    StatusID sId;
    std::string scannerID;
    std::string bulkOption;
    
    std::cout << "Enter Scanner ID : " << std::endl;
    std::cin >> scannerID;
    std::cout << "Enter Firmware DAT file path: " << std::endl;
    std::cin >> datFilePath;
    std::cout << "Enter USB communication mode 1=hid, 2=bulk : ";
    std::cin >> bulkOption;
    
    inXml = "<inArgs><scannerID>" + scannerID + "</scannerID><cmdArgs><arg-string>" + datFilePath + "</arg-string><arg-int>" + bulkOption + "</arg-int></cmdArgs></inArgs>";
    cout << "In XML  : " << inXml << endl << endl;     
    ::ExecCommand(CMD_DEVICE_UPDATE_FIRMWARE, inXml, outXml, &sId);
        
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "Firmware Update command success. " << endl << endl;              
    }
    else
    {
        cout << "Firmware Update command failed. Error code : " << sId << endl;
    } 
    cout << "================================" << endl << endl;    
}
   
void SampleEventListener::FirmwareUpdateFromPlugin()
{
    std::string inXml;
    std::string outXml;
    std::string pluginFilePath=""; 
    StatusID sId;
    std::string scannerID;
    std::string bulkOption;
    
    std::cout << "Enter Scanner ID : " << std::endl;
    std::cin >> scannerID;
    std::cout << "Enter Firmware Plug-in file path: " << std::endl;
    //std::cin >>  pluginFilePath;

    while ( pluginFilePath.size() < 4 ){
        std::getline(std::cin, pluginFilePath);
    }
    
    if ( !(pluginFilePath.substr(pluginFilePath.find_last_of(".")+ 1) == "SCNPLG") ){
        std::cout << "Please Enter a file with extension .SCNPLG." << std::endl << std::endl;
        return;
    }
    
    std::cout << "Enter USB communication mode 1=hid, 2=bulk : ";
    std::cin >> bulkOption;
    
    inXml = "<inArgs><scannerID>" + scannerID + "</scannerID><cmdArgs><arg-string>" + pluginFilePath + "</arg-string><arg-int>" + bulkOption + "</arg-int></cmdArgs></inArgs>";
    cout << "In XML  : " << inXml << endl << endl; 
    ::ExecCommand(CMD_DEVICE_UPDATE_FIRMWARE_FROM_PLUGIN, inXml, outXml, &sId);
    
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "FirmwareUpdate From Plug-in command success. " << endl << endl;              
    }
    else
    {
        cout << "FirmwareUpdate From Plug-in command failed. Error code : " << sId << endl;
    } 
    cout << "================================" << endl << endl;
}
   
void SampleEventListener::StartNewFirmware()
{
    std::string inXml;
    std::string outXml;
    StatusID sId;
    std::string scannerID;
    
    std::cout << "Enter Scanner ID : " << std::endl;
    std::cin >> scannerID;
        
    inXml = "<inArgs><scannerID>" + scannerID + "</scannerID></inArgs>"; 
    cout << "In XML  : " << inXml << endl << endl;   
    ::ExecCommand(CMD_START_NEW_FIRMWARE, inXml, outXml, &sId);
    
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "Start New Firmware command success. " << endl << endl;            
    }
    else
    {
        cout << "Start New Firmware command failed. Error code : " << sId << endl;
    } 
    cout << "================================" << endl << endl;
}
   
void SampleEventListener::AbortFirmwareUpdate()
{
    std::string inXml;
    std::string outXml;
    StatusID sId;
    std::string scannerID;    
    
    std::cout << "Enter Scanner ID : " << std::endl;
    std::cin >> scannerID;
    
    inXml = "<inArgs><scannerID>" + scannerID + "</scannerID></inArgs>";
    cout << "In XML  : " << inXml << endl << endl; 
    ::ExecCommand(CMD_DEVICE_ABORT_UPDATE_FIRMWARE, inXml, outXml, &sId);
    
    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "Abort Firmware Update command success. " << endl << endl;              
    }
    else
    {
        cout << "Abort Firmware Update command failed. Error code : " << sId << endl;
    } 
    cout << "================================" << endl << endl;
}
   
/**
* Method to execute action attribute related commands.
* added to v1.3.0 release.
* @param opCode
*/
void SampleEventListener::ExecuteActionCommand(CmdOpcode opCode)
{
    std::string scannerID = "";
    std::string ledNumber = "";
    std::string beeperCode = "";
    std::string inXml;
    std::string commandName = "";
            
    switch (opCode)
    {
        case CMD_DEVICE_LED_ON:
        case CMD_DEVICE_LED_OFF:
        {
            commandName = "Device LED ON/OFF command ";
            cout << "Enter scanner ID : ";
            cin >> scannerID;
            cout << "Enter LED number : ";
            cin >> ledNumber;

            inXml = "<inArgs><scannerID>" + scannerID + 
                                "</scannerID><cmdArgs><arg-int>" + ledNumber +
                                "</arg-int></cmdArgs></inArgs>";
            break;
        }
        case CMD_DEVICE_BEEP_CONTROL:
        {
            commandName = "Beep command ";
            cout << "Enter scanner ID : ";
            cin >> scannerID;
            cout << "Enter Beeper code : ";
            cin >> beeperCode;

            inXml = "<inArgs><scannerID>" + scannerID + 
                                "</scannerID><cmdArgs><arg-int>" + beeperCode +
                                "</arg-int></cmdArgs></inArgs>";
            break;
        }
        case CMD_DEVICE_SCAN_ENABLE:
        case CMD_DEVICE_SCAN_DISABLE:
        {
            commandName = "Device Scan Enable/Disable command ";
            cout << "Enter scanner ID : ";
            cin >> scannerID;
            inXml = "<inArgs><scannerID>" + scannerID + "</scannerID></inArgs>";
            break;
        }
        case CMD_REBOOT_SCANNER:
        {
            commandName = "Reboot scanner command ";
            cout << "Enter scanner ID : ";
            cin >> scannerID;
            inXml = "<inArgs><scannerID>" + scannerID + "</scannerID></inArgs>";
            break;
        }
        case CMD_DEVICE_AIM_ON:
        case CMD_DEVICE_AIM_OFF:
        {
            commandName = "Device AIM ON/OFF command ";
            cout << "Enter scanner ID : ";
            cin >> scannerID;
            inXml = "<inArgs><scannerID>" + scannerID + "</scannerID></inArgs>";
            break;
        }
        case CMD_LOAD_CONFIGURATION:
        {
            std::string config_file_path = "";
            commandName = "Configuration update ";
            cout << "Enter scanner ID : ";
            cin >> scannerID;
            cout << "Enter configuration file path : ";
            cin.ignore();
            std::getline(std::cin, config_file_path);

            inXml = "<inArgs><scannerID>" + scannerID + "</scannerID>" + 
                    "<cmdArgs><arg-string>" + config_file_path + "</arg-string></cmdArgs>" +
                    "</inArgs>";
            break;
        }
        default:
        {
            commandName = "Default Action command ";
            cout << "Enter scanner ID : ";
            cin >> scannerID;
            inXml = "<inArgs><scannerID>" + scannerID + "</scannerID></inArgs>";
            break;
        }
    }
        
    StatusID sId;
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl; 
    ::ExecCommand(opCode, inXml, outXml, &sId);

    cout << "================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << commandName << "success. " << endl << endl;              
    }
    else
    {
        cout << commandName << "failed. Error code : " << sId << endl;
    } 
    cout << "================================" << endl << endl;
}

/**
* Method to execute switch host mode command (option 20).
*/
void SampleEventListener::SwitchHostMode()
{
    std::string scannerID = "";
    cout << "Enter scanner ID : ";
    cin >> scannerID;
    std::string hostMode = "";
    cout << "Host mode options : " << endl;
    cout << "   1. USB-HIDKB " << endl;
    cout << "   2. USB-SNAPI with imaging " << endl;
    cout << "   3. USB-SNAPI without imaging " << endl;
    cout << "   4. USB-IBMHID " << endl;
    cout << "   5. USB-IBMTT " << endl;
    cout << "Enter host mode to switch into (1-5): ";
    cin >> hostMode;
    std::string hostModeString = "";
    int hostModeInteger = atoi(hostMode.c_str());
    switch (hostModeInteger)
    {
        case 1:
        {
            hostModeString = "XUA-45001-3";
            break;
        }  
        case 2:
        {
            hostModeString = "XUA-45001-9";
            break;
        }
        case 3:
        {
            hostModeString = "XUA-45001-10";
            break;
        } 
        case 4:
        {
            hostModeString = "XUA-45001-1";
            break;
        } 
        case 5:
        {
            hostModeString = "XUA-45001-2";
            break;
        } 
        default:
        {
            cout << "=================================" << endl;
            cout << "Error : Invalid value entered!!!"  << endl;
            cout << "=================================" << endl<< endl;
            return;
        }
    }
    
    std::string inXml = "<inArgs><scannerID>"+ scannerID +"</scannerID><cmdArgs>"
                        "<arg-string>"+ hostModeString +"</arg-string>"
                        "<arg-bool>FALSE</arg-bool><arg-bool>TRUE</arg-bool></cmdArgs></inArgs>";
    
    StatusID sId;    
    std::string outXml;
    cout << "In XML  : " << inXml << endl << endl;   
    ::ExecCommand(CMD_DEVICE_SWITCH_HOST_MODE, inXml, outXml, &sId);
    
    cout << "==================================" << endl;    
    if(sId == STATUS_OK)
    {
        cout << "Switch host mode command success. " << endl;            
    }
    else
    {
        cout << "Switch host mode command failed. Error code : " << sId << endl;
    }
    
    cout << "==================================" << endl << endl;
}

After implementation for the class IEventListenerXml, the main class can create an instance of the class SampleEventListener for the demonstration application. It is mandatory to implement IEventListenerXml class because it is an abstract class provided by zebra-scanner. Following is main.cpp for the sample application.

Main Method Implementation (ConsoleMain.cpp)


/*
* ©2022 Zebra Technologies LLC. All rights reserved.
*/

#include "ConsoleMain.h"
#include "ConsoleSampleEventListener.h"

#include <stdlib.h>
//class LoggingContext;

bool hasAlreadyOpen = false;

int ReturnChoice()
{
    cout << "======Select CoreScanner command====" << endl;
    cout << "=== 1. GetAttribute " << endl;
    cout << "=== 2. GetAllAttributes " << endl;
    cout << "=== 3. Get Scanners " << endl;
    cout << "=== 4. SetAttribute " << endl;
    cout << "=== 5. SetAttribute-Store " << endl;
    cout << "=== 6. Device LED ON or OFF " << endl;
    cout << "=== 7. Scanner Enable " << endl;
    cout << "=== 8. Scanner Disable " << endl;
    cout << "=== 9. Scanner Reboot " << endl;
    cout << "== 10. Action - Beeper command" << endl;
    cout << "== 11. AIM ON" << endl;
    cout << "== 12. AIM OFF" << endl;
    cout << "== 13. Get Device Topology" << endl;
    cout << "== 14. Firmware Update" << endl;
    cout << "== 15. Start New Firmware" << endl;
    cout << "== 16. Abort Firmware Update" << endl;
    cout << "== 17. Firmware Update From Plugin"<< std::endl;
    cout << "== 18. Get Version "<< endl;
    cout << "== 19. GetNextAttribute " << endl;
    cout << "== 20. Switch Host Mode - permanent" << endl;
    cout << "== 21. Configuration Update " << endl;
        
    cout << "====================================" << endl;
    cout << "=== 0. Exit" << endl;
    cout << "= 100. Main Menu" << endl;
    //cout << "====================================" << endl;
    //cout << "== 7. SetScaleZero " << endl;
    //cout << "== 8. Discover Tunneling " << endl;
    //cout << "== 9. Open called again " << endl;
    cout << "====================================" << endl;
    cout << "Enter choice : " ;
            
    int choice = 0;
    cin >> choice;
    return choice;
}

int main(void)
{
    cout << "Zebra Scanner Sample Application" << endl;
    cout << "====================================" << endl;

    SampleEventListener sel;
    SampleEventListener sel2;

    if(STATUS_OK != sel.Open())
    {
        std::cout << "Corescanner service is not Active." << std::endl;
        return STATUS_ERROR;
    }
        
    sel.GetScanners();

    int choice = ReturnChoice();

    do 
    {
        switch (choice) 
        {
            case 1:
                sel.GetAttribute();
                break;
            case 2:
                sel.GetAllAttributes();
                break;
            case 3:
                sel.GetScanners();
                break;
            case 4:
                sel.SetAttribute();
                break;
            case 5:
                sel.SetAttributeStore();
                break;  
            case 6:
                sel.ExecuteActionCommand(CMD_DEVICE_LED_ON);
                break;
            case 7:
                sel.ExecuteActionCommand(CMD_DEVICE_SCAN_ENABLE);
                break;
            case 8:
                sel.ExecuteActionCommand(CMD_DEVICE_SCAN_DISABLE);
                break;
            case 9:
                sel.ExecuteActionCommand(CMD_REBOOT_SCANNER);
                break;
            case 10:
                sel.ExecuteActionCommand(CMD_DEVICE_BEEP_CONTROL);
                break;
            case 11:
                sel.ExecuteActionCommand(CMD_DEVICE_AIM_ON);
                break;
            case 12:
                sel.ExecuteActionCommand(CMD_DEVICE_AIM_OFF);
                break;
            case 13:
                sel.GetDeviceTopology();
                break;
            case 14:
                sel.FirmwareUpdate();
                break;
            case 15:
                sel.StartNewFirmware();
                break;
            case 16:
                sel.AbortFirmwareUpdate();
                break;
            case 17:
                sel.FirmwareUpdateFromPlugin();
                break;
            case 18:
                sel.GetVersion();
                break;
            case 19:
                sel.GetAttributeNext();
                break;
            case 20:
                sel.SwitchHostMode();
                break;
            case 21:
                sel.ExecuteActionCommand(CMD_LOAD_CONFIGURATION);
                break;	
            case 100:
                cout << "====================================" << endl;
                break;
            case 0:
            default:
                break;
        }
                
        if(choice != 0)
        {
            choice = ReturnChoice();
        }

    } 
    while (choice);
    
    sel.Close();
    return 0;
}

Calling Open Command


void SampleEventListener::Open()
{
    StatusID status;
    ::Open(this, SCANNER_TYPE_ALL, &status);

    // register for all events.
    std::string inXml = "<inArgs><cmdArgs><arg-int>6</arg-int><arg-int>1,2,4,8,16,32</arg-int></cmdArgs></inArgs>";

    std::string outXml;
    ::ExecCommand(CMD_REGISTER_FOR_EVENTS, inXml, outXml, &status);
}

Calling Close Command


void SampleEventListener::Close()
{
    StatusID status;
    ::Close(0, &status);
}

Calling GetScanners Command


void SampleEventListener::GetScanners()
{
    unsigned short count;
    vector<unsigned int> list;
    string outXml;
    StatusID eStatus;

    ::GetScanners(&count, &list, outXml, &eStatus);

    cout << "GetScanners" << endl;
    cout << outXml << endl;
}

Calling ExecCommand Command


void SampleEventListener::GetAttribute()
{
    cout << "================================" << endl;
    cout << "GetAttribute " << endl;
    std::string scannerID = "";
    
    cout << "Enter Scanner ID" << endl;
    cin >> scannerID;
    
    cout << "Enter attribute number or comma separated attribute numbers : ";
    std::string attribute_number = "";
    cin >> attribute_number;

    std::string inXml = "<inArgs><scannerID>" + 
                        scannerID +
                        "</scannerID><cmdArgs><arg-xml><attrib_list>" +
                        attribute_number + 
                        "</attrib_list></arg-xml></cmdArgs></inArgs>";

    cout << "In XML : " << inXml << endl << endl;
    StatusID sId;
    std::string outXml;
    ::ExecCommand(CMD_RSM_ATTR_GET, inXml, outXml, &sId);

    cout << "Out XML : " << outXml << endl;
    cout << "================================" << endl;
}