Barcode Lookup in External IT Systems

Using Flow to consume an API (simple RESTful API or ERP system, such as SAP)

In this tutorial, we will show you how you can build a simple solution, called activity in Flow, to scan a barcode and retrieve some associated information from your existing IT system, e.g. a product database, a CRM system, an ERP system or just a plain simple RESTful API.
As an example solution, we will create a Barcode Lookup activity for an imaginary company that operates a fleet of cars (equipments). This activity can be used to retrieve information about their cars, either by scanning a barcode attached to the car, or by scanning a barcode on the documents associated with a particular car. This could mean that just by scanning the car, an employee can quickly look up e.g. when the next maintenance service is due, or by scanning any document, the location of the relevant car.

Step 1: Setup

As a first step, we will need to create a new activity. On the Flow Web Dashboard, go to Activities and add a new activity by choosing "Run your own code". Choose any name you like, select ECMAScript 6 (.es6) as the default language and hit Save. If you're not familiar with ES6, don't worry, this activity is simple enough for someone with knowledge of a language like JavaScript, Java, C# or similar.

Now that you have your blank activity created and the web editor open, you'll have to decide if you want to edit the code in the web editor or locally on your computer. With the web editor, you can simply make your changes in the browser and publish your activity easily to use it on a device, while in local development you can choose the tools you prefer and additionally run your activity on a device locally, without publishing. If you're interested in setting up local development, either with the Flow Desktop App or with the sflow CLI, you can find out more in our Getting Started with Local Development guide - you can continue from here once you have everything working. If you choose the web editor, you have nothing else to do, so let's start!

You can find the web editor again by going to Activities and clicking the icon next to your activity.

Step 2: Starting the barcode scanner

First, open src/scripts/app.es6, this is the file that we'll do most of the work in. Let's start the barcode scanner and reorganize our code a little bit, this is the code that we will develop in this step:

src/scripts/app.es6

class App {
  start() {
    this.startScanner();
  }

  startScanner() {
    this.scanner = this.scanner || new Scandit.BarcodeScanner({symbologies: ['code128']});
    this.scanner.show().start();

    this.scanner.on('scan', barcode => {
      console.log(barcode);
    });
  }

  showEquipment(equipment) {
    Scandit.Ui.Views.load('src/views/view.html', {equipment: equipment});
  }
}

const app = new App();
Scandit.Activity.onReady(() => {
    app.start();
});

Let's walk this through, starting out from the blank template that Flow generates for every activity. We first delete the empty constructor function, as we don't need to do any special initialization on instantiation. After that, we move the loading of the view into a separate function (showEquipment) and pass it an argument which will be assigned to the view as equipment. At this point, we should also update our view to use this variable:

Change src/views/view.html to this:

<p>{{ equipment }}</p>

After that's done, let's get back to app.es6: we create a new function, startScanner which we call in start. The startScanner function will take care of instantiating the scanner (only if it does not exist yet) and starting it. Calling start() after show() is needed in this case, as the scanner is initially shown in a paused state and we want it to be ready for scanning, so we also have to explicitly start it. We then subscribe to the scan event emitted by the scanner and log the scanned barcode to the console.

At this point, you are ready to try out your modified activity. In the web editor, publish to the group your device is assigned to, or if you're in local development, you can run your activity locally, as explained in the Getting Started with Local Development guide. After scanning the barcode below, you should be able to see it logged to the console.

Example Barcode

Step 3: Fetching via HTTP

Now that we've got the barcode scanning working, let's fetch the equipment (car) from the API. To achieve this, we'll modify our src/scripts/app.es6 so that it looks like this:

src/scripts/app.es6

class App {
  start() {
    this.startScanner();
  }

  startScanner() {
    Scandit.Activity.off('backPressed');
    this.scanner = this.scanner || new Scandit.BarcodeScanner({symbologies: ['code128']});
    this.scanner.show().start();

    this.scanner.on('scan', barcode => {
      this.scanner.off('scan');
      this.getEquipment(barcode);
    });
  }

  getEquipment(equipmentNumber) {
    Scandit.Http.get(`https://docs.scandit.com/flow/assets/equipments/${equipmentNumber}`)
    .then(httpResponse => {
      if (httpResponse.status === 200) {
        return Promise.resolve(JSON.parse(httpResponse.body));
      } else {
        return Promise.reject(httpResponse.status === 404 ? 'Equipment not found' : 'Error while fetching the equipment');
      }
    })
    .then(equipment => {
      this.showEquipment(equipment);
    })
    .catch(error => {
      this.scanner.setTextOverlay(error.message || error);
      this.startScanner();
    });
  }

  showEquipment(equipment) {
    Scandit.Ui.Views.load('src/views/view.html', {equipment: equipment});
    this.scanner.hide();
    Scandit.Activity.on('backPressed', () => { this.startScanner(); });
  }
}

const app = new App();
Scandit.Activity.onReady(() => {
  app.start();
});

Let's see what we have to add:

We create a function getEquipment that takes one argument, the equipment number, which will be the scanned barcode. In this function, we use Scandit.Http.get to make a GET request to the API, creating the URL on the fly with the equipmentNumber. This function returns a Promise that is resolved with the HTTP response.
A Promise represents a single async operation that is expected to complete in the future. It can either be pending, fulfilled or rejected. When a promise becomes fulfilled or rejected, the associated handlers (.then() and .catch()) are called. To learn more about Promises, take a look at the official documentation.
As we'll be chaining together multiple Promises, handling errors is as easy as checking if the HTTP response status code was a 200, in which case we got back the equipment we requested and can resolve with the JavaScript object representation of the returned JSON object.
If the status code was something different than 200, we hit an error so we reject the whole Promise and pass in a human readable string depending on what the error was.

The next step is handling a successful Promise (when there was an equipment returned), in which case we simply call the showEquipment function and pass in the parsed JSON object. For this to work as we want it to, we also have to add two lines to the showEquipment function, the first hides the scanner and the second starts the scanner when the back button is pressed. We are actually subscribing to the backPressed event, so we also need to unsubscribe from it when the scanner is started, as we want to go back to the activity list when we tap the back button while the scanner is shown, hence the first line of the startScanner function.

Getting back to our function for fetching the equipment from the API, we also need to handle the case when the Promise is rejected. The .catch handles errors that happened at any time in the Promises and caused it to be rejected. We show a human readable string over the scanner explaining what happened and start the scanner again.
The error message could be directly from the server (e.g. 404) or it could also be that the device couldn't even try to make the request, e.g. there was no network connection. The latter would be a Scandit.Error, which has a message property, the former simply a string that we pass.

At this point, if you were to run your activity, the view would simply say [object Object], so let's fix that and populate it with the information we just fetched from the API.

Step 4: Updating the view

Now that we've got all the logic covered, all we need to do is display our data! Let's replace src/views/view.html with the following:

src/views/view.html

{{#equipment}}
<table>
  <thead>
    <tr><th>Equipment Number</th><th>{{equipment_number}}</th></tr>
  </thead>
  <tbody>
    <tr><td>Manufacturer</td><td>{{manufacturer}}</td></tr>
    <tr><td>Mode</td><td>{{model}}</td></tr>
    <tr><td>Type</td><td>{{type}}</td></tr>
    <tr><td>Acquisition Value</td><td>${{acquisition_value}}</td></tr>
    <tr><td>Acquisition Date</td><td>{{acquisition_date}}</td></tr>
    <tr><td>Location</td><td>{{location}}</td></tr>
    <tr><td>Next Maintenance</td><td>{{next_maintenance}}</td></tr>
  </tbody>
</table>
{{/}}

As the view loaded by Scandit.Ui.Views is a Ractive instance, we can simply use the {{ expression }} interpolation syntax to display the data. Wrapping the table with a context using {{#equipment}}...{{/}} makes it possible to simply use {{equipment_number}} instead of {{equipment.equipment_number}}, which saves us a lot of keystrokes! To learn more about Ractive, you can find more information under Scandit.Ui.Views.

Publishing the final activity

Now that we've updated the view to display the data, all that's left to do is publish the activity and try it out on a device! In the web editor, simply hit publish and choose the groups you're targeting. If you're using the Flow Desktop app or sflow, you can refer to the Getting Started with Local Development guide for information on how to publish your activity. For some debugging tips and tricks, check out the Debugging Flow Activities guide.

Next steps

Consuming JSON returned by a web API could just as well mean letting your users search a list of products and displaying the results, or showing your employees details about the order they have to preprocess. The possibilities are endless and this tutorial simply serves as a starting point to help you get started.

This activity can be easily modified to connect to your own system, such as a simple RESTful API, a CRM system, or an ERP system. After setting the API endpoint URL, you'll probably want to edit the view to display your own data.

Tip: To connect to your SAP system and consume the data it provides in your activity, you can easily activate the OData service in SAP NetWeaver Gateway Service Builder (SEGW). You also have to make sure that your API is accessible through the internet. This way you could easily consume the data from your SAP system, the activity would only need minor modifications.