Cognex Mobile Barcode SDK for WEB

Requirements

Server-side    A secure HTTPS connection on the server, which hosts the web application.

Client-side    Latest versions of all major browsers: Chrome, Firefox, Safari, Edge, and Opera.

Grant permission for the site to access the camera if necessary.

Installation

Place the following files into your web application:

  • assets (icons directory)
  • barcode-scanner-preview-style.css
  • cognex_icon.png
  • index.html                                                                             //example
  • index.js
  • index.wasm
  • main.js
  • MWBConfig_wa.js
  • MWBScanner_wa.js
  • sdk_modular.js

The index.html page is not part of the SDK. It serves only as an example of scripts to include and usage of the exposed API methods.

Include the following scripts on the page:

	<script type="text/javascript" src="MWBScanner_wa.js"></script>
	<script type="text/javascript" src="MWBConfig_wa.js"></script>
	<script type="text/javascript" src="sdk_modular.js"></script>
	<script type="text/javascript" src="main.js"></script>
	<script async type="text/javascript" src="index.js"></script>

Installation with Webpack

Call webpack from the project directory. This builds the source files from /src into a bundle.js file and places it into the /dist directory.

The ./src/main.js file serves as an entry point. It contains an example of how to use the cmbWEB SDK. The other files are part of the SDK.

The /dist directory contains all the necessary files:

  • assets (icons directory)
  • bundle.js                                                                                //built with webpack
  • index.html                                                                             //example
  • index.js
  • index.wasm

 

The index.html page is not part of the SDK. It serves only as an example of scripts to include and usage of the exposed API methods.

Include the following scripts on the page:

	<script src=" bundle.js"></script>
	<script src=" index.js"></script>
Note: index.js (global scope) and index.wasm have to be present.

The structure of the final solution should be much like the one in the /dist directory.

It’s also important where the page, index.html in this example, that includes index.js and the webpack built file, bundle.js in this case, is located in relation to index.wasm and cognex_icon.png.

Make sure that these are in the same directory to avoid any possible issues.

However, if index.js and bundle.js reside in a different directory, they still expect index.wasm and cognex_icon.png to be in the directory they are called in, that is, the directory of the HTML page.

The path of index.wasm can be set through the return statement of the setWasmPath method in MWBConfig_wa.js. In the webpack version this method (that is, the return of it) should be used as an argument:

	MWB.setWasmPath(MWBCfg.setWasmPath());

in main.js or you could set a custom string here directly:

	MWB.setWasmPath("example_path/index.wasm");

 

Configuration

The scanner is configured through the MWBConfig_wa.js file. The MWBConfig_wa.js file contains the following:

  • Subscribing to scannerModuleLoaded event, after which the scanner is ready to be used and its methods to be invoked. This process could take longer on slower devices and slower networks.
		document.addEventListener("scannerModuleLoaded", function(e) {
			console.log(e.detail); //Prints "Scanner is ready."
			//can use mwbScanner.* methods now
		});
 Note: Attempting to use the API, for example making the scan call before the scanner is ready, meaning that the scannerModuleLoaded has not fired yet, would result in an error, as it can take some time for the cmbWEB SDK to load and start up, so the API after the scannerModuleLoaded event has to be used. 
  • Getting available cameras and setting a desired camera. Usually for situations where the device has multiple back cameras, and the one without auto-focus is used by default.

See an example for this operation in the MWBConfig_wa.js file. The comments can be removed from this example to make it useable:

	mwbScanner.getCameras().then(function(foundCameras){
			let cameraCount = foundCameras.length;
			console.log("Cameras found: " + cameraCount);
			
			//list found cameras with label / name and id
			for (let i = 0; i < cameraCount; i++)
				console.log("Camera " + i + " name: " + foundCameras[i].label + " with ID: " + foundCameras[i].id);
			
			//use desired camera.id for the param
			let desiredCameraIndex = 0;
			let desiredCameraId = foundCameras[desiredCameraIndex].id;
			mwbScanner.setCamera(desiredCameraId); //overrides the effect of the MWBuseFrontCamera setting

			//can use mwbScanner.startScanning methods now
		});
 Note: When using the getCamera methods, wait for the operations to complete before using the scanner. 
  • Setting an example callback for handling the return from mwbScanner.startScanning, when a barcode is found or the scan is canceled.
		mwbScanner.setCallback(
			function (result) {
				if (result.type != "Multicode") {
					if (result.type == "Cancel") console.log("No Barcode.");
					else alert(result.type + '\n' + result.code);
				}
				//detailed example for handling result.type == "Multicode"
				//is found in MWBConfig_wa.js
			}
		);

 

Possible result types other than symbology type for a found barcode:

mwbScanner.startScanning method:

    • "Error" if an error has occurred, more information included in the result.code
    • "Cancel" when the previously started scan is canceled by means of mwbScanner.closeScanner or a timeout
    • "Multicode" when there are multiple barcode detections in a single image/frame

mwbScanner.scanImage and mwbScanner.scanFrame methods:

    • "NoResult" if no barcode has been found/detected
    • "Multicode" when there are multiple barcode detections in a single image/frame
  • The result object that is returned to the callback function of mwbScanner.startScanning or mwbScanner.scanImage has the following format:
	//if using multicode:
	result.code 		- empty string
	result.type 		- string "Multicode"
	result.count 		- the number of detected barcodes
	result.codes 		- json array of detected barcodes in the result format below


	//if using single code (or single code result.codes array elements in case of multicode):
	result.code 		- string representation of barcode result
	result.parsedCode 	- string json representation of parsed barcode result (if any)
	result.type 		- type of barcode detected or 'Cancel' if scanning is canceled
	result.bytes 		- bytes array of raw barcode result
	result.isGS1 		- (boolean) barcode is GS1 compliant
	result.location 	- contains rectangle points p1,p2,p3,p4 with the corresponding x,y
	result.imageWidth 	- Width of the scanned image
	result.imageHeight 	- Height of the scanned image

 

  • Configuring settings with an array of key:value pairs for methods and values for their arguments which are invoked when the scanner is loaded and/or started. The comments from the settings can be removed, and their values can be changed.
	var mw_c =  mwbScanner.getConstants(),
	settings = [
			//{"method" : "MWBsetLevel", "value" : [2]}, //1-5
			{"method" : "MWBsetDecoderTimeout", "value" : [30]} //10-60
	];

 See all configuration methods and parameters listed in the following sections.

Usage | Exposed API Methods

Once all the modules have loaded and the scanner is ready, meaning that the scannerModuleLoaded event has fired. Invoke the exposed methods from the mwbScanner object:

  • mwbScanner.startScanning method:

fullscreen scanner:

	mwbScanner.startScanning()
	mwbScanner.startScanning(function callback)

partial view scanner:

	mwbScanner.startScanning(x, y, width, height)
	mwbScanner.startScanning(function callback, x, y, width, height)

x, y, width, height                      - rectangle of the view in percentages relative to the screen size

callback                                       - result callback

  • mwbScanner.scanImage method:
	mwbScanner.scanImage(URI)
	mwbScanner.scanImage(URI, function callback)

 

URI                                                  - the path to the image

callback                                          - result callback

  • Examples and remaining exposed API methods
	Scan fullscreen		-  mwbScanner.startScanning()
	Scan in view		-  mwbScanner.startScanning(5,5,90,50)
	Scan image			-  mwbScanner.scanImage('test_img.png')
	Pause/Resume		-  mwbScanner.togglePauseResume()
	Resume				-  mwbScanner.resumeScanning()
	Close				-  mwbScanner.closeScanner()
	Flash				-  mwbScanner.toggleFlash()
	Zoom				-  mwbScanner.toggleZoom()

	Resize partial view	-  mwbScanner.resizePartialScanner(25,25,50,50)

 

  • mwbScanner.scanFrame method
	mwbScanner.scanFrame(ImageData | dataURL)
	mwbScanner.scanFrame(ImageData | dataURL, function callback)

 

ImageData | dataURL               - either an object of type ImageData OR a dataURL image string

callback                                       - result callback

Note: Using ImageData is convenient and faster, because the data is already in the desired format. The only requirement is that the data remains unchanged during the scan, until it is copied to memory.
Note: Using dataURL is slower and not recommended for live scanning scenarios. The actual data is represented in base64 in an appropriate encoding/compressing format, for example, png or jpeg. It requires extra decoding steps to get the raw pixel format, which takes significant time.
Note: MW_methods.helpers.reset_Decoder(); and scannerConfig(); are called on each start of this method. However, they can be unnecessary, if scanning rects, viewfinder area the decoder scans for each symbology with values 0-100%, are not modified at any other point than the initial config.

Licensing the SDK

Licensing is done by using an image that contains the licensing information. The license key is one of these images.

  • Configuring the license image (path)name:

The sample SDK comes with a license image file cognex_icon.png, which does not contain a license, it only serves as an example. The actual license image file can have a different name and/or path, for example, carrier_icon.png.

The license image name, and path if a different directory is used is specified in the MWBConfig_wa.js file, by passing the (path)name as an argument on the mwbScanner.setIcon() method.

	mwbScanner.setIcon("carrier_icon.png");

The image file carrier_icon.png is expected to be in the same directory as the index.html file, which includes the .js file, that calls the setIcon method.

Using a path works in relation to the index.html file in this example, or the root of the server in case of:

  • Obtaining a license

Request a license on https://cmbdn.cognex.com/lpr. If the page is inaccessible, permission for wasm licenses, request approval from the person or team that manages the used cmbDN account.

After clicking request license and selecting CMBWEB/Wasm License, the site navigates to the WASM License Purchase Request page where a license can be created by generating a small image from the provided information, such as:

  • the type of license evaluation / commercial / non-production / production
  • the licensing period – usually preset by type
  • domain(s) / host(s) the web sdk will run on. Instead of a regular domain, a wildcard host or an IP address can be used in specific use cases.
Note: A custom logo can be uploaded to be used instead of the default Cognex logo.

The generated image serves as a carrier for the licensing information.

Note: Unless otherwise specified, browsers cache these resources, and upon an eventual license upgrade a new image needs to be acquired instead of the cached one. The simplest way is to use a different name, possibly with a version number.

Configuration Methods and Parameters

The following methods are meant to be used in a settings array in MWBConfig_wa.js:

@name "MWBsetActiveCodes"  Sets active or inactive status of decoder types     
@param[in]	activeCodes   ORed bit flags (MWB_CODE_MASK_...) of decoder types to be activated.

  @n       MWB_CODE_MASK_NONE
  @n       MWB_CODE_MASK_QR
  @n       MWB_CODE_MASK_DM
  @n       MWB_CODE_MASK_RSS
  @n       MWB_CODE_MASK_39
  @n       MWB_CODE_MASK_EANUPC
  @n       MWB_CODE_MASK_128
  @n       MWB_CODE_MASK_PDF
  @n       MWB_CODE_MASK_AZTEC
  @n       MWB_CODE_MASK_25
  @n       MWB_CODE_MASK_93
  @n       MWB_CODE_MASK_CODABAR
  @n       MWB_CODE_MASK_DOTCODE
  @n       MWB_CODE_MASK_11
  @n       MWB_CODE_MASK_MSI
  @n       MWB_CODE_MASK_MAXICODE
  @n       MWB_CODE_MASK_POSTAL
  @n       MWB_CODE_MASK_TELEPEN
  @n       MWB_CODE_MASK_ALL   

CodeMask constants are available for all codeMask variables

@name "MWBsetActiveSubcodes"  Set active subcodes for given code group flag.  Subcodes under some decoder type are all activated by default.

@param[in]  codeMask    Single decoder type/group (MWB_CODE_MASK_...)
@param[in]  subMask     ORed bit flags of requested decoder subtypes (MWB_SUBC_MASK_)

@name "MWBsetFlags"   Sets active or inactive status of decoder types    
@param[in]   codeMask   Single decoder type (MWB_CODE_MASK_...)
@param[in]   flags      ORed bit mask of selected decoder type options (MWB_FLAG_...)

@name "MWBsetMinLength" configures minimum result length for decoder type specified in codeMask.
@param[in]   codeMask   Single decoder type (MWB_CODE_MASK_...)
@param[in]   minLength  Minimum result length for selected decoder type

@name "MWBsetDirection" 
@param[in]   direction   ORed bit mask of direction modes given with MWB_SCANDIRECTION_... bit-masks
@n     MWB_SCANDIRECTION_HORIZONTAL - horizontal lines
@n     MWB_SCANDIRECTION_VERTICAL - vertical lines
@n     MWB_SCANDIRECTION_OMNI - omnidirectional lines
@n     MWB_SCANDIRECTION_AUTODETECT - enables BarcodeScanners autodetection of barcode direction
@n     MWB_SCANDIRECTION_CUSTOM - custom barcode direction

@name "MWBsetScanningRect"
Sets the scanning rectangle
Parameters are interpreted as percentage of image dimensions, i.e. ranges are 0 - 100 for all parameters.
@param[in]   codeMask    Single decoder type selector (MWB_CODE_MASK_...)
@param[in]   left        X coordinate of left edge (percentage)
@param[in]   top         Y coordinate of top edge (percentage)
@param[in]   width       Rectangle witdh (x axis) (percentage)
@param[in]   height      Rectangle height (y axis) (percentage)

@name "MWBsetLevel"
Effort level of the scanner values can be 
@param[in]   level     1,2,3,4 and 5
example : [{"method" : "MWBsetLevel", "value" : [3]}]    

@name "MWBsetOverlayMode"
@param[in]    OverlayMode
@n  OverlayModeNone     No overlay is displayed
@n  OverlayModeMW       Use MW Dynamic Viewfinder with blinking line
@n  OverlayModeImage    Show image on top of camera preview
example : [{"method" : "MWBsetOverlayMode", "value" : [mw_c.OverlayModeImage]}]    

@name "MWBresizePartialScanner"
Resizes partial scanner dimensions. If usePartialScanner is true the scanner will open in a window with these dimensions
@param[in]   left      X coordinate of left edge (percentage)
@param[in]   top       Y coordinate of top edge (percentage)
@param[in]   width     Rectangle witdh (x axis) (percentage)
@param[in]   height    Rectangle height (y axis) (percentage)
example : [{"method" : "MWBresizePartialScanner", "value" : [0,0,50,50]}]    

@name "MWBusePartialScanner"
Boolean value that opens a partial scanner if set true
@param[in]   bool               true/false
example : [{"method" : "MWBusePartialScanner", "value" : [true]}]

@name "MWBsetActiveParser"
Set active parser types
@param[in]    ActiveParser    ORed values
@n      MWP_PARSER_MASK_NONE
@n      MWP_PARSER_MASK_AUTO
@n      MWP_PARSER_MASK_GS1
@n      MWP_PARSER_MASK_IUID
@n      MWP_PARSER_MASK_ISBT
@n      MWP_PARSER_MASK_AAMVA
@n      MWP_PARSER_MASK_HIBC
@n      MWP_PARSER_MASK_SCM    
example : [{"method" : "MWBsetActiveParser", "value" : [mw_c.MWP_PARSER_MASK_GS1 | mw_c.MWP_PARSER_MASK_IUID]}]




//additional settings:

@name "MWBsetBlinkingLineVisible"
Set blinking line visible
Default value is true
@param[in]	visible
example : [{"method" : "MWBsetBlinkingLineVisible", "value" : [true]}]

@name "MWBsetPauseMode"
What happens when the scanner is paused
Default value is PM_STOP_BLINKING
@param[in]	pauseMode
@n	PM_NONE             - Nothing happens
@n	PM_PAUSE            - Blinking lines are replaced with a pause view
@n	PM_STOP_BLINKING    - Blinking lines stop blinking
example : [{"method" : "MWBsetPauseMode", "value" : [mw_c.PM_STOP_BLINKING]}]

@name "MWBenableHiRes"
Enable or disable high resolution scanning. It is recommended to enable it when target barcodes are of high density or small footprint. If device does not support high resolution param will be ignored
Accepts boolean (false - 480p, true - 720p) or constants (mw_c.CamRes_SD - 480p, mw_c.CamRes_HD - 720p, mw_c.CamRes_FHD - 1080p)
Default value is true (enabled) / CamRes_HD (720p)
@param[in]	enableHiRes
example : [{"method" : "MWBenableHiRes", "value" : [true]}]

@name "MWBenableFlash"
Enable or disable flash toggle button on scanning screen. If device does not support flash mode button will be hidden regardles of param
Default value is true (enabled)
@param[in]	enableFlash
example : [{"method" : "MWBenableFlash", "value" : [true]}]

@name "MWBturnFlashOn"
Set default state of flash (torch) when scanner activity is started
Default value is false (disabled)
@param[in]	flashOn
example : [{"method" : "MWBturnFlashOn", "value" : [false]}]

@name "MWBenableZoom"
Enable or disable zoom button on scanning screen. If device does not support zoom,
button will be hidden regardles of param.
Default value is true (enabled)
@param[in]	enableZoom
example : [{"method" : "MWBenableZoom", "value" : [true]}]

@name "MWBsetZoomLevel"
Set desired initial zoom level. Zoom is supported only by chrome. Initial zoom level can be 0 - no zoom, 1 - 50% or 2 - max zoom. Default is 0. 
@param[in]   zoomLevel     0,1 and 2
example : [{"method" : "MWBsetZoomLevel", "value" : [1]}]

@name "MWBcloseScannerOnDecode"
Enable/disable continuous scanning. If 'shouldClose' is 'false', result callback will be performed and scanner will be paused. The User can call 'resumeScanning' to continue scanning, or 'closeScanner' for closing the scanner. Default is 'true'.
@param[in]	shouldClose
example : [{"method" : "MWBcloseScannerOnDecode", "value" : [true]}]

@name "MWBsetParam"
Set custom decoder param id / value pair for decoder type specified in a codeMask.
@param[in]	codeMask                Single decoder type (MWB_CODE_MASK_...)
@param[in]	paramId                 ID of param
@param[in]	paramValue              Integer value of param
example : [{"method" : "MWBsetParam", "value" : [codeMask, paramId, paramValue]}]

@name "MWBduplicateCodeDelay"
Ignore result if scanned the same code in continuous scanning mode
@param[in]	delay         Time interval between 2 scan results with the same result.code in milliseconds
example : [{"method" : "MWBduplicateCodeDelay", "value" : [1000]}]

@name "MWBuseFrontCamera"
Use front facing camera
@param[in]	useFrontCamera   Whether or not to use front facing camera
Default value is false
example : [{"method" : "MWBuseFrontCamera", "value" : [false]}]

@name "MWBsetDecoderTimeout"
The amount of time in seconds the camera preview in either partial view or full screen mode will be on before closeScanner is called. 
@param[in]   	timeout     10-60
example : [{"method" : "MWBsetDecoderTimeout", "value" : [30]}] 

@name "MWBsetDpsLimit"
Decodes per second, i.e. number of frames that are sent for decoding in a given second. This setting only works with our camera preview i.e. when using the startScanning method.
@param[in]   	dpsLimit     1-30
example : [{"method" : "MWBsetDpsLimit", "value" : [2]}]

Most of the additional settings configure only the implementation of the camera preview. In the case of using a custom preview or camera feed with the scanFrame method, it is up to implementation to limit the number of frames that are decoded in a given second, meaning the number of calls to scanFrame. This affects performance, especially on iOS.

Performance and Browser Support

As described in previous sections, WebAssembly makes CPU intensive execution at near-native speeds available on the client-side. This means that the performance of the device in question can be limited by its hardware capabilities. In general, the decoding speed is faster on desktop computers and far slower on mobile devices. Browser support for various features tends to favor desktop versions as well.

Currently the best browser support is provided by Google Chrome. Other browsers do well in general, with some known differences at this time:

  • Firefox offers camera choice regardless whether the front/back camera was specified. Firefox also has no flash/zoom API support.
  • Safari requires an additional user click to start the camera/video for the first time, and does not keep the choice for future page access. Safari also has no flash/zoom API support.
  • All execution on Safari on iOS is on the main thread. This happens because the decoder is the part that uses the CPU the most, it can compete with the camera preview, and the user would end up with a lot of lag.

The user can improve performance regarding the last point in a few ways:

  • Use of dpsLimit value decodes per second, meaning the number of frames that are sent for decoding in a given second, is recommended, such as 1 or 2 at the most. In realistic use cases, there is no practical need for a higher decoding rate, even on devices that are capable of such performance.
  • Limit symbologies to only the ones needed. Single symbology decoding, for example just QR code decoding. This is not necessarily notable at all lag wise, even though it is on the same thread.
  • Using a lower effort level decoder, and/or a lower camera resolution can also help reduce lag and stutter produced by CPU overuse.

Example configuration for improving performance on iOS Safari:

	{"method" : "MWBsetDpsLimit", "value" : [1]},
	{"method" : "MWBsetActiveCodes", "value" : [ mw_c.MWB_CODE_MASK_QR ]},
	{"method" : "MWBsetLevel", "value" : [1]},
	{"method" : "MWBenableHiRes", "value" : [false]}
Note: Some codes like PDF require a higher effort level and can have include detail which cannot be captured with lower camera resolution. Consider these capture limitations, when choosing between 720p (default) or 480p.

 

There are some other differences in what APIs the browsers provide, however we aim to mitigate differences as much as possible to provide a consistent experience across different platforms.