# Cognex Mobile Barcode Scanner Web SDK

This programmers API documentation is based on a TypeScript interface for our JavaScript library to better describe method signatures and expected parameter types.

## Documentation and integration info

The cmbWeb documentation and integration info is available on this page (jump to Documentation Contents)

> Note: Documentation is also available on cmbDN and will continue to be for a while, but ultimately documentation will only be available here.

## API Methods

All of the API methods can be found here. Usage and examples can be found here

## Configuration Methods

All of the configuration methods, usage and examples can be found can be found here

## Changelog

Detailed changelog can be found on our developer network site

#### Documentation Contents

Requirements
Installation overview
Installation with plain JS
Installation with Webpack
Installation with Webpack (inline wasm)
Installation with npm
Integration with Blazor (no Blazor UI)
Integration with ReactJS
Integration with Angular
Integration with VueJS
Configuration
Subscribing to scannerModuleLoaded event
Getting available cameras and setting the desired camera
Enabling the camera switcher on the cameraPreview
Setting a default callback method
Configuring settings
Usage | Exposed API Methods
Licensing the SDK
Configuring the license path / name
Obtaining and configuring a license
Sample app
Performance and Browser Support
Web vs native performance

## 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 overview

The cmbWeb release comes in multiple variants:

1. plain/vanilla js     - front_end directory of the cmbWeb download
2. webpack       - webpack directory of the cmbWeb download
3. webpack inline     - webpack_inline directory of the cmbWeb download
4. npm package     - https://www.npmjs.com/package/cmbsdk-cmbweb

Main differences between the multiple variants are as follows:

- Plain / Vanilla JS can run directly in the browser. Its suitable for quickly trying things out.
- The webpack and webpack inline variants need to be built (i.e. packaged, bundled) first. Most (but not all) of the files cmbWeb comes with will be bundled, thus the resulting solution will be more compact. In the case of webpack inline, the index.wasm file is embedded, thus you don't need to worry about loading it.
- The cmbsdk-cmbweb npm package can run directly in the browser, or it can be used as a nodejs module. All of the files cmbWeb comes with are embedded in a single JS file so you only need to use one file for cmbWeb and one more for configuring it.

Difference between using a solution with the index.wasm file or having it embedded:

- Plain / Vanilla JS and webpack have a setWasmPath method in the MWBConfig_wa.js file, where you can specify a different location for the index.wasm file, whereas webpack inline and the npm package embed it, thus they don't have the setWasmPath method.
- Having the index.wasm file embedded means you don't need to worry about loading it (e.g. having the correct 'application/wasm' MIME type on your server, compatibility in different environments, setting the correct path, etc.), but this comes at the cost of a larger size, about 33% more for the embedded format.

The one resource that does not come embedded in any variant is the licensing image; all variants expect to load the licensing image - this can be changed via the mwbScanner.setIcon method already present in the MWBConfig_wa.js file (see Configuring the license image).

You can go over the installation details below for each variant.

## Installation with plain JS

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

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

Include the following scripts on the index.html 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

1. 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.

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

The /dist directory contains all the necessary files:

- assets (icons directory)
- cognex_icon.png
- bundle.js             // Built with webpack
- index.html            // Example
- index.js
- index.wasm

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

3. 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 the index.html, index.wasm, and cognex_icon.png files are in the same directory, as the index.js and bundle.js files expect to find them in the directory of the HTML page.
  - This is true even 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 of the HTML page they are included in.
  - If you wish to change this you can do so by specifying another path through the mwbScanner.setIcon and setWasmPath methods respectively.
- 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");

## Installation with Webpack (inline wasm)

1. 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.

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

The /dist directory contains all the necessary files:

- assets (icons directory)
- cognex_icon.png
- bundle.js             // Built with webpack
- index.html            // Example

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

3. Include the following scripts on the page:

        <script src="bundle.js"></script>

> Note: Unlike the standard webpack version, this version inlines the wasm binary within the js source files, thus index.js and index.wasm are no longer 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 the webpack built file, bundle.js in this case, is located in relation to cognex_icon.png.
  - Make sure that the index.html and cognex_icon.png files are in the same directory, as the bundle.js file expects to find cognex_icon.png in the directory of the HTML page.
  - This is true even if bundle.js resides in a different directory - they still expects cognex_icon.png to be in the directory of the HTML page it is included in.
  - If you wish to change this you can do so by specifying another path through the mwbScanner.setIcon method.
- As index.wasm is removed in this version, the setWasmPath method is also removed.

## Installation with npm

1. Run npm i cmbsdk-cmbweb. This will copy the npm package content to node_modules/cmbsdk-cmbweb/ and also add the package to your package.json if you already have one.

2. The node_modules/cmbsdk-cmbweb/cmbweb.js file contains the entire SDK and also serves as an entry point.

The node_modules/cmbsdk-cmbweb/ directory contains all the necessary files:

- cmbweb.js
- cognex_icon.png
- MWBConfig_wa.js
- index.html            // Example

3. Include the following script on the page:

- For usage directly in browser:

        <script type="text/javascript" src="cmbweb.js"></script>
        <script type="text/javascript" src="MWBConfig_wa.js"></script>

        //copy the following files to your page's directory:
        //cmbweb.js  			//cmbWeb SDK
        //MWBConfig_wa.js		//your custom configuration
        //cognex_icon.png		//your license image (may have a different name)

> Note: Unlike the vanilla js and webpack versions, this version inlines the wasm binary, the css file and the assets within the js source file.

The structure of the final solution should be much like the one in the /node_modules/cmbsdk-cmbweb/ directory.

- For usage as a nodejs module:

        //in your entry point file:
        var mwbScanner = require('cmbsdk-cmbweb');
        window.mwbScanner = mwbScanner;

        <!-- in your page: -->

        <!-- a bundled file for the browser that contains cmbsdk-cmbweb -->
        <script src="./bundle.js"></script>
        <!-- a custom cmbweb configuration file -->
        <script type="text/javascript" src="MWBConfig_wa.js"></script>

        //copy the following files to your page's directory:
        //MWBConfig_wa.js		//your custom configuration
        //cognex_icon.png		//your license image (may have a different name)

- It's also important where the page, index.html in this example, that includes the cmbweb.js / bundle.js file, is located in relation to cognex_icon.png.
  - Make sure that the index.html and cognex_icon.png files are in the same directory, as the cmbweb.js / bundle.js file expects to find cognex_icon.png in the directory of the HTML page.
  - This is true even if cmbweb.js / bundle.js resides in a different directory - it still expects cognex_icon.png to be in the directory of the HTML page it is included in.
  - If you wish to change this you can do so by specifying another path through the mwbScanner.setIcon method.

## Integration with Blazor (no Blazor UI)

The cmbsdk-cmbweb npm package variant of the cmbWEB SDK is the most suitable for integration with Blazor. Refer to the previous section for installation details.

In a Blazor WebAssembly App created from a project template in Visual Studio, you need to do the following to add and use cmbWEB in it:

1. Copy the cmbweb.js, MWBConfig_wa.js, cognex_icon.png (and test_img.png if you want) files into wwwroot.

2. Then, in index.html:

        <script src="_framework/blazor.webassembly.js"></script>

        //after including blazor.webassembly.js, include the following cmbWEB files:
        <script src="./cmbweb.js"></script>
        <script type="text/javascript" src="MWBConfig_wa.js"></script>

With that, everything is set. Once the browser loads everything, you can start using the API, for example:

        mwbScanner.startScanning(function(res){ console.log(res); }, 25,25,50,50);

on a button click, which will start a cameraPreview and start scanning. You can check out the API here.

Note that, this is using cmbWeb side-by-side with Blazor; the UI from cmbWeb is HTML and it does DOM manipulation which is fine as long as you don't intend Blazor to be aware of it, as stated:

> Only mutate the Document Object Model (DOM) with JavaScript (JS) when the object doesn't interact with Blazor. Blazor maintains representations of the DOM and interacts directly with DOM objects.

## Integration with ReactJS

The webpack inline variant of the cmbWEB SDK is the most suitable for integration with ReactJS. Refer to the previous section for details.

In a ReactJS App, you need to do the following to add and use cmbWEB in it:

> Note: Provided ReactJS demo app in the cmbWEB download already does steps 1, 2, 3 and 5, thus if you're using the demo, you only need to do step 4.

1. Copy the bundle.js file from webpack_inline/dist into reactJS_sampleApp/src/cmbweb/

2. Open bundle.js and add the following comments on top:

    /* eslint-disable no-unused-expressions */
    /* eslint-disable no-restricted-globals */
    /* eslint-disable no-undef */

These will disable linting code patterns that eslint typically considers errors, which if not disabled would cause the build to fail.

There are also other code patterns that eslint considers warnings, and while the build will still succeed, the output log might be overpopulated with warnings. So, it is ok to disable all rule warnings for the entire bundle.js file:

    /* eslint-disable */

> Note: Provided ReactJS demo app in the cmbWEB download already does steps 1 and 2 under prebuild scripts in the package.json file.

3. Import bundle.js into your source file:

    import MWBScannerSDK from './cmbweb/bundle.js';

and start using the cmbWeb API into methods of ReactJS components:

    class Trigger extends React.Component {
      start() {
        mwbScanner.startScanning(10,20,80,40);
      }
      stop() {
        mwbScanner.closeScanner();
      }
      render() {
        return (
        <React.Fragment>
          <button onClick={this.start}>Start Scanner</button>
          <button onClick={this.stop}>Stop Scanner</button>
        </React.Fragment>
        );
      }
    }

Using the startScanning method as such will create an HTML cameraPreview and dynamically add it to the DOM. This might not be an issue, but since ReactJS maintains its own internal DOM representation, that means ReactJS is unaware of changes made to the DOM outside of ReactJS, which could potentially lead to unwanted behaviour.

Thus, a better approach is using a container element for adding the cameraPreview to:

    class Container extends React.Component {
      id = "cmbweb-preview-container"
      divStyle = {
        border: 'blue',
        position: 'fixed',
        top: '25%',
        left: '25%',
        width: '50%',
        height: '30%',
        backgroundColor: 'gray'
      }
      render() {
        return <div id={this.id} style={this.divStyle}/>;
      }
    }

> Note: Provided ReactJS demo app in the cmbWEB download already does step 3 in the /src/sampleapp.js file.

##### 4. Run the following commands:

    npm install				//needed only 1st time
    npm run-script build

from the react directory to create the react build from that source.

5. Copy assets, cognex_icon.png (or your license image file, that you have set in MWBConfig_wa.js in the webpack_inline project), and test_img.png from webpack_inline/dist into the newly generated build directory (this step is needed each time a new build is created).

> Note: Provided ReactJS demo app in the cmbWEB download already does step 5 under postbuild scripts in the package.json file.

You can now host the build directory and open it in a browser.

####

Related guides

### Using production vs development deployment

The above (copying the resources to build and hosting build directory) refers to production deployment use cases i.e. the build directory will be hosted under a webserver such as apache for example. Of course you may use the same setup during development as well.

If however, you wish to try things out during development by using the node server via npm start for example, you would need to also copy above resources to the public directory (as the node server will only serve the page and files within the Module System, whereas external files are served from the public directory).

Since resources in the public directory are copied to the build directory automatically during the build process, you may simplify things regarding the copy of needed external resources listed above, by droping the postbuild script, and just prepending the following code at the start of the prebuild script:

        shx cp -r ../webpack_inline/dist/assets public && shx cp ../webpack_inline/dist/cognex_icon.png public && shx cp ../webpack_inline/dist/test_img.png public &&

so the start of the prebuild script looks like this:

        "prebuild": "shx cp -r ../webpack_inline/dist/assets public && shx cp ../webpack_inline/dist/cognex_icon_.png public && shx cp ../webpack_inline/dist/test_img.png public && node -e \"var fs = require('fs'); ....

### Adding a license and changing the configuration

Provided ReactJS demo app uses the output of the webpack_inline project. This means any change, such as adding a license or changing the default configuration, needs to be done in the webpack_inline project, and after a change, the webpack_inline project has to be re-built, and subsequently, the ReactJS demo app has to be re-built as well.

#### To add (or replace) a license:

1. Copy your license image file to webpack_inline/dist (for this example lets assume this is your_license.png)

2. Open webpack_inline/src/MWBConfig_wa.js and change the argument of the mwbScanner.setIcon method i.e. it should now be `mwbScanner.setIcon("your_license.png")`

3. Re-build the webpack_inline project i.e. run `node_modules/.bin/webpack`. Now webpack_inline/dist should have a new bundle.js file referencing your_license.png

4. Open reactjs_demo/package.json and change the license file name (from the default cognex_icon.png) to your_license.png in all places it is used in the prebuild/postbuild script

5. Re-build the ReactJS demo app i.e. run `npm run-script build`

#### To change the configuration, i.e. to use different settings, result callback, or event listener:

1. Open webpack_inline/src/MWBConfig_wa.js or webpack_inline/src/main.js and make the desired changes.

2. Re-build the webpack_inline project i.e. run `node_modules/.bin/webpack`

3. Re-build the ReactJS demo app i.e. run `npm run-script build`

## Integration with Angular

The npm package variant of the cmbWEB SDK is the most suitable for integration with Angular. Refer to the previous section for details.

In an Angular app, you need to do the following to add and use cmbWEB in it:

> Note: Provided Angular demo app in the cmbWEB download already does steps 1, 2, 3 and 4, thus if you're using the demo, you only need to do step 5.

1. Add the cmbsdk-cmbweb npm package:

    npm i cmbsdk-cmbweb

2. Open package.json and:

- under "scripts": { ... } make sure you have

        "build": "ng build",

The built page includes a base tag with href attribute for referencing includes resources, such as scripts, css files, etc. Most likely you will need to provide the path of the built directory for this property, and you can do so with

        "build": "ng build --base-href /path_on_the_web_server/angular_demo/dist/cmbweb-angular-demo/",

Replace path_on_the_web_server with the actual path on your web server.

- under "scripts": { ... } add the following

        "postbuild": "shx cp ./node_modules/cmbsdk-cmbweb/MWBConfig_wa.js ./dist/cmbweb-angular-demo && shx cp ./node_modules/cmbsdk-cmbweb/cognex_icon.png ./dist/cmbweb-angular-demo",

The postbuild script will copy the MWBConfig_wa.js and cognex_icon.png files to the output directory after a build. It relies on the shx, so you need to add it as well:

    npm i shx

> Note: Your particular license image may be differently named than cognex_icon.png and reside in a different location, and if so, you'll need to adjust the postbuild script with the correct filename and path. The same is true for MWBConfig_wa.js if you're using a different location for it.

> Note: cmbweb-angular-demo is the name of the provided Angular demo app in the cmbWEB download. Your Angular app may have a different name.

3. Import and use cmbsdk-cmbweb into your src/app source files:

Since cmbsdk-cmbweb is a UMD Module and not an ES Module nor is it written in TypeScript, standard import practises won't work. Instead, using import * as _ works in such cases.

app.component.ts

    // @ts-ignore
    import * as _ from 'cmbsdk-cmbweb';

After that, you can move on to using the cmbWeb API into methods of Angular components:

app.component.ts

    export class AppComponent {
      title = 'cmbWeb demo';

      constructor() {

        //make mwbScanner global
        (window as any).mwbScanner = _;
      }

      public startScanning(): void {

        (window as any).mwbScanner.startScanning();
      }

      public closeScanner(): void {

        (window as any).mwbScanner.closeScanner();
      }
    }

app.component.html

    <div id="ui-buttons">
        <button id="start-scan-button" (click)="startScanning()">
        Start Scanner
        </button>

        <button id="stop-scan-button" (click)="closeScanner()">
        Stop Scanner
        </button>
    </div>

    <br/>

    <div id="cmbweb-preview-container" style="border:1px solid; position:fixed; top:25%; left:25%; width:50%; height:30%; background-color:gray;"></div>

Make sure the built page includes MWBConfig_wa.js i.e. modify

src/index.html

    <body>
      <app-root></app-root>
      <script type="text/javascript" src="MWBConfig_wa.js"></script>
    </body>

4. Edit the angular.json file:

- under projects > cmbweb-angular-demo > architect > build > options add the following

        "allowedCommonJsDependencies": [
                  "cmbsdk-cmbweb"
                ],

> Note: the "cmbweb-angular-demo" field is the name of the provided Angular demo app in the cmbWEB download. Your Angular app may have a different name.

- under projects > cmbweb-angular-demo > architect > build > configurations > production > budgets [{ ... }] modify the "maximumError" value to 2mb (or more, as cmbweb.js is currently just under 2mb)

        "maximumError": "2mb"

##### 5. Run the following commands:

    npm install				//needed only 1st time
    npm run-script build		//see note below before running this line

from the angular directory to create the angular build from that source.

> Note: Before creating a build, you will need to change the base-href argument with a valid path. If you have already set a valid path (in step 2 or otherwise) you can skip this part.

To change the base-href path, open package.json and under "scripts": { ... }

        "build": "ng build --base-href /path_on_the_web_server/angular_demo/dist/cmbweb-angular-demo/",

replace path_on_the_web_server with the actual path on your web server.

You can now host the dist/cmbweb-angular-demo directory and open it in a browser.

####

Related guides

### Using production vs development deployment

The above (copying the resources to dist/cmbweb-angular-demo and hosting dist/cmbweb-angular-demo directory via the postbuild script) refers to production deployment use cases i.e. the dist/cmbweb-angular-demo directory will be hosted under a webserver such as apache for example. Of course you may use the same setup during development as well.

If however, you wish to try things out during development by using the node server via npm start for example, you would need to also copy above resources to the src directory and list them in the build.options.assets key of the angular.json file (as the node server will only serve the page and files within the Module System, whereas external files are served from what is specified in the build.options.assets key of the angular.json file).

Since those resources are copied to the dist/cmbweb-angular-demo directory automatically during the build process, you may simplify things regarding the copy of needed external resources listed above, by droping the postbuild script, and just using the following code in the prebuild script:

        "prebuild": "shx cp ./node_modules/cmbsdk-cmbweb/MWBConfig_wa.js ./src && shx cp ./node_modules/cmbsdk-cmbweb/cognex_icon.png ./src"

and adding the following code under build.options.assets:

        "assets": [
                  ....
                  "src/MWBConfig_wa.js",
                  "src/cognex_icon.png"
                ],

### Adding a license and changing the configuration

Provided Angular demo app uses the cmbsdk-cmbweb npm package. This means any change, such as adding a license or changing the default configuration, needs to be done in the webpack_inline project, and after a change, the webpack_inline project has to be re-built, and subsequently, the ReactJS demo app has to be re-built as well.

#### To add (or replace) a license:

1. Copy your license image file to node_modules/cmbsdk-cmbweb (for this example lets assume this is your_license.png)

2. Open node_modules/cmbsdk-cmbweb/MWBConfig_wa.js and change the argument of the mwbScanner.setIcon method i.e. it should now be `mwbScanner.setIcon("your_license.png")`

3. Open angular_demo/package.json and change the license file name (from the default cognex_icon.png) to your_license.png in the prebuild/postbuild script, as well as in the build.options.assets key in angular_demo/angular.json

4. Re-build the Angular demo app i.e. run `npm run-script build`

#### To change the configuration, i.e. to use different settings, result callback, or event listener:

1. Open node_modules/cmbsdk-cmbweb/MWBConfig_wa.js and make the desired changes.

2. Re-build the Angular demo app i.e. run `npm run-script build`

## Integration with VueJS

The npm package variant of the cmbWEB SDK is the most suitable for integration with VueJS. Refer to the previous section for details.

> Note: Provided VueJS demo app is implemented in Vue 3.

In a VueJS app, you need to do the following to add and use cmbWEB in it:

> Note: Provided VueJS demo app in the cmbWEB download already does step 1 (as well as all other steps for using a build tool), thus if you're using the demo, you only need to do step 5.

1. Add the cmbsdk-cmbweb npm package:

    npm i cmbsdk-cmbweb

### Using NO BUILD TOOL

> Note: Provided vuejs_demo/standalone already does listed changes, thus if you're using the demo, it is ready for use in a browser. The standalone demo makes use of the Options API.

Open index.html and:

- include the following scripts:

        <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
        <script src="../node_modules/cmbsdk-cmbweb/cmbweb.js"></script>
        <script src="../node_modules/cmbsdk-cmbweb/MWBConfig_wa.js"></script>

- use the cmbWeb API into methods of a Vue component:

                startScanning() {
                    mwbScanner.startScanning(this.resultCallback)
                },
                stopScanning() {
                    mwbScanner.closeScanner()
                }

        <button @click="startScanning">Start Scanner</button>
        <button @click="stopScanning">Stop Scanner</button>

        <br>

        <div id="cmbweb-preview-container" style="border:1px solid; position:fixed; top:25%; left:25%; width:50%; height:30%; background-color:gray;"></div>

- make sure a license image file (e.g. cognex_icon.png) is present in the standalone directory (set via setIcon in MWBConfig_wa.js)

        mwbScanner.setIcon("cognex_icon.png");

### Using a BUILD TOOL (Vite)

> Note: Provided vuejs_demo already does steps 2, 3 and 4, thus if you're using the demo, you only need to do step 5. The build demo is created with the official Vue project scaffolding tool, and makes use of the Composition API + Single-File Components.

2. Open package.json and:

- under "scripts": { ... } add the following

        "prebuild": "shx cp ./node_modules/cmbsdk-cmbweb/MWBConfig_wa.js public && shx cp ./node_modules/cmbsdk-cmbweb/cognex_icon.png public",

The prebuild script will copy the MWBConfig_wa.js and cognex_icon.png files to the public directory, which are then copied to the output directory after a build. It relies on the shx, so you need to add it as well:

    npm i shx

> Note: Your particular license image may be differently named than cognex_icon.png and reside in a different location, and if so, you'll need to adjust the prebuild script with the correct filename and path. The same is true for MWBConfig_wa.js if you're using a different location for it.

3. Import and use cmbsdk-cmbweb into your src/components source files:

Since cmbsdk-cmbweb is a UMD Module and not an ES Module nor is it written in TypeScript, standard import practises won't work. Instead, using import _ from works in such cases.

SampleApp.vue

    import _ from 'cmbsdk-cmbweb';

- use the cmbWeb API into methods of the Vue component:

    function startScanning() {
        mwbScanner.startScanning(resultCallback)
    }
    function stopScanning() {
        mwbScanner.closeScanner()
    }

    // lifecycle hooks

    onMounted(() => {
        window.mwbScanner = _
    })

        <button @click="startScanning">Start Scanner</button>
        <button @click="stopScanning">Stop Scanner</button>

        <br>

        <div id="cmbweb-preview-container" style="border:1px solid; position:fixed; top:25%; left:25%; width:50%; height:30%; background-color:gray;"></div>

Make sure the built page includes MWBConfig_wa.js i.e. modify

index.html

      <body>
        <div id="app"></div>
        <script type="module" src="/src/main.js"></script>
        <script type="text/javascript" src="MWBConfig_wa.js"></script>
      </body>

4. Edit the vite.config.js file:

- in the json argument for defineConfig({ ... }) add the following

      base: './',
      build: {
          chunkSizeWarningLimit: 2000
      }

> Note: chunkSizeWarningLimit can also be set to a higher value than 2000kb as cmbweb.js is currently just under 2mb.

##### 5. Run the following commands:

    npm install				//needed only 1st time
    npm run build

from the vue directory to create the vue build from that source.

You can now host the dist directory (production build) or standalone directory (no build tool) and open it in a browser.

## Configuration

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

- ##### Subscribing to scannerModuleLoaded event

After this event the scanner is ready to be used and its methods can be invoked. The scanner load and start up 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
        });

See the example event listener.

- ##### Getting available cameras and setting the desired camera

Usually for situations where the device has multiple rear cameras, and the one without auto-focus is used by default.
There is a commented-out example for doing this in the MWBConfig_wa.js file:

        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
        });

See the getCameras and setCamera methods.

> Note: When it comes to choosing which of the cameras to use for situations where the device has multiple back cameras, and the one without auto-focus is used by default, currently there is no indicator which one has auto-focus so you will have to try which one works best. However, there seems to be a common denominator for the back camera with AF - it will typically have a label like "camera2 0, facing back" so the back camera with a "0" in the label is usually the best one.

- ##### Enabling the camera switcher on the cameraPreview

Usually for situations where the device has multiple cameras, the camera switcher UI lists all found cameras, and allows to switch to a different camera. Doing so stops the current scanning and starts a new scanning session with the chosen camera.
The camera switcher is enabled in the MWBConfig_wa.js file with the following setting:

        {"method" : "MWBenableCameraSwitcher", "value" : [true]}

See the MWBsetCameraSwitcherOptions configuration method.

- ##### Setting a default callback method

The following is an example for setting a default callback for handling the return from mwbScanner.startScanning, when a barcode is found, the scan is canceled or an error has occurred:

        mwbScanner.setCallback(
            function(result) {

                if (result.type == "Error") console.log(result.errorDetails);
                else if (result.type == "Cancel") console.log("No Barcode.");
                else if (result.type == "NoResult") console.log("No Barcode.");

                else if (result.type == "Multicode")
                {
                    let resultCodes_string = "";
                    let foundCodes = result.count;
                    for (let i = 0; i < foundCodes; i++)
                    {
                        resultCodes_string += result.codes[i].type + '\n' + result.codes[i].code + '\n';

                    }
                    mwbScanner.beep();
                    console.log(result.type + '\n\n' + resultCodes_string);
                }
                else
                {
                    mwbScanner.beep();
                    console.log(result.type + '\n' + result.code);

                    //mwbScanner.resumeScanning(); //if using !MWBcloseScannerOnDecode
                }
            }
        );

See the example callback method.

- ##### Configuring settings

This is done 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.

        var mw_c = mwbScanner.getConstants(),
        settings = [
            {"method" : "MWBsetActiveCodes", "value" : [
                mw_c.MWB_CODE_MASK_QR |
                mw_c.MWB_CODE_MASK_DM |
                //mw_c.MWB_CODE_MASK_RSS |
                //mw_c.MWB_CODE_MASK_39 |
                mw_c.MWB_CODE_MASK_EANUPC |
                mw_c.MWB_CODE_MASK_128 |
                mw_c.MWB_CODE_MASK_PDF |
                //mw_c.MWB_CODE_MASK_AZTEC |
                //mw_c.MWB_CODE_MASK_25 |
                //mw_c.MWB_CODE_MASK_93 |
                //mw_c.MWB_CODE_MASK_CODABAR |
                //mw_c.MWB_CODE_MASK_DOTCODE |
                //mw_c.MWB_CODE_MASK_11 |
                //mw_c.MWB_CODE_MASK_MSI |
                //mw_c.MWB_CODE_MASK_MAXICODE |
                //mw_c.MWB_CODE_MASK_POSTAL |
                //mw_c.MWB_CODE_MASK_TELEPEN |
                0x0 //for binary-OR syntax purposes
            ]}
            ,{"method" : "MWBsetLevel", "value" : [2]}
            ,{"method" : "MWBenableHiRes", "value" : [mw_c.CamRes_HD]}
            ,{"method" : "MWBsetDecoderTimeout", "value" : [10]}
            ,{"method" : "MWBsetDpsLimit", "value" : [2]}
        ];

        mwbScanner.loadSettings(settings);

See all configuration methods and configuration stage.

> Note: Some of the settings listed in the MWBConfig_wa.js file are commented-out and can be uncommented to enable them, and their values can be changed.

## Usage | Exposed API Methods

The mwbScanner object is the main object which exposes the cmbWeb API.

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

Scanning methods:

mwbScanner.startScanning
mwbScanner.scanImage
mwbScanner.scanFrame

Scan control methods:

mwbScanner.closeScanner
mwbScanner.resumeScanning
mwbScanner.togglePauseResume

Camera preview UI controling methods:

mwbScanner.resizePartialScanner
mwbScanner.setBlinkingLineVisible
mwbScanner.setScannerOverlayMode
mwbScanner.toggleFlash
mwbScanner.toggleZoom

Examples:

        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)

## Licensing the SDK

Licensing is done by using an image that contains the licensing information. You can see such an image file as the license key itself.

- ##### Configuring the license image (path)name:

The cmbWEB SDK sample 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.

Use mwbScanner.setIcon() to specify the license image name and path in the MWBConfig_wa.js file by including the path and image name as an argument.

        mwbScanner.setIcon("carrier_icon.png");

The image file carrier_icon.png is expected to be in the same directory as the index.html file and 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 /path

The setIcon method can be overloaded with two arguments.

        mwbScanner.setIcon(iconURI, allowCrossOrigin);

The setIcon method now also accepts a 2nd argument (boolean) which if set to true allows cross origin, otherwise if set to false or not used at all it keeps the default (no cross origin).

        mwbScanner.setIcon("carrier_icon.png", true);

This would enable the option of using a license image that is hosted on another server i.e. originates from another domain than the one the web app is hosted on, such as a CDN for example.

> Note: The server hosting the licensing image also needs to be configured to allow CORS for it.

- License status (if invalid, expired or invalid domain) will be provided in e.detail of the scannerModuleLoaded event, see Subscribing to scannerModuleLoaded event in the Configuration section.
  Possible values:
  - "Scanner is ready."
  - "Invalid domain."
  - "Invalid license."
  - "Expired license."

> Note: Regardless of string value the scanner is ready once the scannerModuleEvent has fired (results will be masked if not licensed).

- ##### Obtaining and configuring a license

Request a license on https://cmbdn.cognex.com/lpr.

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 you will need to ensure you're getting the new image (and not the cached one). The simplest way is to use a different name, possibly with a version number.

- #### Licensing issue specific to licensing images

We have received reports of licensing issues in recent versions of Chrome (120+) on Android. In our investigation we noticed the licensing data (coming from a licensing image) is corrupted past a certain size. This is most likely due to recent changes in how images are handled in Chrome/Chromium i.e. canvas element, png decompression, etc.

Licensing images with a single domain might go unaffected (due to the size being just below the point where the data corrution happens), however, our recommendation is to switch from a licensing image to a textual license. The license remains the same, only the format is different (image vs. text/string).

Switching from an image license to a text license involves:

1. Obtaining a text license

   - Go to your LPR (i.e. https://cmbdn.cognex.com/lpr/[your_lpr_id] where [your_lpr_id] is the number of the LPR) page.
   - Scroll down to where the license keys are listed - typically this section will have one or more licensing images. Click on the licensing image that you are currently using in your web app (i.e. the one that you want to replace with a text license instead).
   - In the panel that opens up, you will notice a field named WASM String License. Copy the content of that field - this is the textual license (it is the same as the licensing image, its just provided in a different format).

2. Replacing the licensing image used in the SDK with the text license

   - Remove

           mwbScanner.setIcon("license_image.png");

   - Add

           mwbScanner.setKey("textual_license");

Note that the textual license is at least 512 characters long. Also note that you will need to use the latest version of cmbWeb (v1.5.3). In this version reloading the page should suffice for the new change to take effect. Otherwise clear the device's cache.

## Sample app

Each variant comes with a sampleApp directory, which makes use of the cmbWeb SDK.

Files specific to the sample app are:

- index.html
- sample_app_UI.js
- sample-app-style.css
- icon-sprite.svg
- MWBConfig_wa.js

There are slight differences in what index.html includes and in how MWBConfig_wa.js carries out the configuration, specific to each variant, but other than that, the content of the sample app is identical for all.

> Note: if you are using webpack or webpack inline, you'll need to replace the src/MWBConfig_wa.js file with sampleApp/MWBConfig_wa.js and re-build so that the sample app's config file is used in the built bundle.js file.

> Note: the MWBConfig_wa.js file uses the optional chaining operator (?.) which has recently gained support in all browsers.

When it comes to what most will be of interest for utilizing cmbWeb, you can check out the following files:

- index.html - Has static UI buttons and basic API usage
- sample_app_UI.js - Dynamically fills the page with UI elements for configuring the scanner
- MWBConfig_wa.js - Makes use of stored configuration values set by UI elements (see sample_app_UI.js)

For taking a closer look at the sample_app_UI.js file, you can skip the GUI_helper object and check out the event listener method for the "scannerModuleLoaded" event, as well as the add_gui_controls method.

## 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 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 of whether the front/back camera was specified. Firefox also has no flash/zoom API support.

- Camera video streaming is available to non-Safari browsers from iOS 14.3

  - Underlying implementation for features such as camera access and DOM rendering tends to be subpar in non-Safari browsers, resulting in higher completion time during resize or orientation change events. Due to this, some reduced smoothness may be observed in the camera preview transformation during an orientation change.

- 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.

You can improve Safari iOS performance in the following 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. With single symbology decoding, for example just QR code decoding, there might be no lag and stutter noticeable, even though it is on the same thread.
- Using a lower effort level for the 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 detail which cannot be captured with lower camera resolution. Consider these capture limitations, when choosing between 480p, 720p (default) or 1080p for demanding barcodes.

The APIs that different browsers provide may differ in other ways, however, we aim to mitigate differences as much as possible to provide a consistent experience across different platforms.

- ##### Web vs native performance

When it comes to using a web or a native SDK, both can scan with similar performance but a native solution (android or iOS SDK) is slightly better because natively there is a slightly better camera focus, and that affects the scan the most.

For the most part, this slight difference in camera focus won't be an issue, but, depending on your use case, such as cases where your code has a high density, it might take more time to scan compared to a native solution.

In such demanding cases, you might do fine with either 720p or 1080p resolution, but your camera must have auto-focus otherwise you'll have a hard time getting a clear frame and a successful scan. If not, then maybe a better barcode sample with a larger size might offset the lack of camera quality.

In general, while higher-end mobile devices are better, there is no limit to how low-end you can go with a particular mobile device, again, as long as it has a good enough camera with autofocus (of course you should test for your use case to see how suitable it is).

Generated using TypeDoc