QBOID Confidential and Proprietary Information
Perceptor products provide 2 different sets of APIs that would cover different use case scenarios:
In addition, Perceptor products place at the disposal the following features:
Supported applications
This documentation covers the following M2 applications developed and maintained by QBOID:
Item and Parcel Dimensioning App
Throughout this document, it will be referred to as Parcel
This application enables the automatic measurement of the length, width, and height of both cuboidal and irregular-shaped items and parcels. It can optionally integrate with Bluetooth scales for seamless weight acquisition.
When the M2 device is connected to the S1 accessory, the same application is used for operation.
Pallet Dimensioning App
Throughout this document, it will be referred to as Pallet
This application automatically computes the dimensions of a pallet (length, width, and height) by analyzing individual faces. This method allows dimensioning even when the entire pallet is not fully visible from a single perspective.
The QBOID equipment responsible for generating dimensioning records. It can be either a Perceptor M2 or S1.
The system that receives and processes dimensioning records from the QBOID device.
A dimensioning record is a structure containing the information about a single item for either the WiFi or the Intent APIs. It is generally formatted as a JSON string with a structure like the following:
{ "timestamp": "2021\/02\/14 07:19:38", "l": 195, "w": 165, "h": 72, "weight": 7709, "barcode": "845973030506", "shape": "Cuboidal", "device": "FH0402211100001", "note": "", "attributes": { "hazmat": "true" }, "image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEU..." }
| Field | Format | Description |
|---|---|---|
timestamp |
string yyyy/MM/dd HH:mm:ss |
UTC timestamp using the Device time. Hour format is (0-23). |
l |
int |
Length of the item in mm. Length is defined as the biggest among the 2 measurements parallel to the ground plane. Parcel When the option Mandatory dimensioning is disabled, this field will be set to -1 if any dimensional field (l,w,h) is missing. |
w |
int |
Width of the item in mm. Width is defined as the smallest among the 2 measurements parallel to the ground plane. Parcel When the option Mandatory dimensioning is disabled, this field will be set to -1 if any dimensional field (l,w,h) is missing. |
h |
int |
Height of the item in mm. Height is defined as the measurement orthogonal to the ground plane. Parcel When the option Mandatory dimensioning is disabled, this field will be set to -1 if any dimensional field (l,w,h) is missing. |
weight |
int (Optional) |
Weight of the item in g (grams). |
barcode |
string |
|
shape |
string |
Currently supported values are Irregular and Cuboidal. Additional shapes will be supported in the future. Filled only by the Parcel App. When the option Mandatory dimensioning is disabled, this field will be set to an empty String if dimensional information is missing. |
device |
string |
Device serial number. Same as shown in Settings -> System -> About Phone -> Status -> Serial number. |
note |
string |
User-composed alphanumeric note string. |
attributes |
map(string->string) {} when empty |
Contains the values assigned using the attributes buttons. Attribute buttons are fully customizable; any arbitrary combination of key/value may be present. |
image |
string PNG/JPEG base64 image (Optional) |
Full resolution color image with bounding box drawn on top. Can be enabled/disabled in settings. The default image format is JPEG, while PNG can be selected in the application settings. (See WiFi API Settings for more info) |
imagecolor |
string PNG/JPEG base64 image (Optional) |
Full resolution color image without bounding box drawn on top. Can be enabled/disabled in settings. The default image format is JPEG, while PNG can be selected in the application settings. (See WiFi API Settings for more info) |
imageseg |
string PNG/JPEG base64 image (Optional) |
Color image cropped to show the dimensioned object. Used only by the Parcel App. Can be enabled/disabled in settings. The background can be configured to be transparent. The default image format is JPEG, but PNG may be used depending on the application settings for format and transparency. (See WiFi API Settings for more info) |
String fields are escaped as per JSON standard, more specifically:
| Input | Output |
|---|---|
New Line |
\n |
\ |
\\ |
/ |
\/ |
Carriage return |
\r |
Tab |
\t |
Images are encoded in the JSON request as a Data URI scheme with a base64 encoding adhering RFC-2045.
Following is an example of an encoded image:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAHklEQVR42mP8z8AARNQDjKMGjho4auCogaMGjlQDAUwCJ+0NBcXlAAAAAElFTkSuQmCC Note: Previous string can be copied and pasted to browser address bar to visualize the image.
Note: RFC-2045 specification requires that: The encoded output stream must be represented in lines of no more than 76 characters each.. For that reason, the encoded images will contain line breaks (i.e.: \n) that must be ignored by the decoding software.
This is a REST-like API where a JSON message is sent to a local or internet HTTP endpoint, and is designed to be familiar to developers doing client server web development.
Once the scan event is completed, either manually by an operator specific key press, or automatically by QBOID software, the dimensioning record is immediately queued up for offloading to a remote resource, e.g. a WMS system or manifesting software.
The Device will send a POST request with a JSON body to the HTTP endpoint defined in its configuration expecting a 200-299 HTTP response code.
There are two groups of settings that can impact the data transmitted through the WiFi API:
Acquisition is a collection of parameters that will affect the data acquisition during the dimensioning process. Adjusting these settings will not affect the sequences already collected, unless otherwise specified.WiFi API is a collection of parameters for configuring the data transmitted over WiFi. Changing these settings will affect the sequences already collected, unless otherwise specified.Acquisition settings
Added in 2.4.0
Acquisition parameters can be configured in the M2 applications.
| Entry | Default | App | Description |
|---|---|---|---|
Settings > Developers Settings > Color Resolution |
0.3MP |
Parcel | Defines which camera should be used for acquiring the color image.0.3MP: will collect a 640x480 image with the low-resolution sensor, which is also used for the preview. The camera is located in the middle of the main sensor bar.13MP: will collect a 4160x3120 image with the high-resolution camera situated beneath the main sensor bar and near the flashlight.Note: Sequences captured at a resolution of 13MP will consume approximately 6MB of storage space, whereas 0.3MP sequences will only use around 1MB of storage space. |
Settings > Data Settings > Acquisition > Compute Alpha Channel |
disabled |
Parcel | If enabled, a foreground/background image segmentation will be performed on the result and pixels that belong to the background will have the alpha channel set to 0 on the segmented image (i.e.: imageseg field).The image format for imageseg will be forced to PNG when Compute Alpha Channel is enabled regardless of the value of Use JPEG format |
WiFi API settings
Optional fields, image format and endpoint can be configured in the M2 applications in the section: Settings -> Data Settings -> WiFi API.
| Entry | Default | App | Description |
|---|---|---|---|
API endpoint |
http://192.168.7.100:5000/newEntry |
Parcel Pallet | Define the URL for the HTTP/HTTPS endpoint. |
Upload timeout |
5 |
Parcel Pallet | Define the connection and data read timeout in seconds. |
Upload result image |
disabled |
Parcel Pallet | Enable/Disable the image field. |
Upload color image |
disabled |
Parcel Pallet | Enable/Disable the imagecolor field. |
Upload segmented image |
disabled |
Parcel Pallet | Enable/Disable the imageseg field. |
Use JPEG format |
enabled |
Parcel Pallet | When enabled, JPEG format will be used for image, imagecolor and imageseg fields when transferred over WiFi.PNG will instead be used if the option is disabled.imageseg will be forced to PNG when Compute Alpha Channel is enabled, regardless of the value of Use JPEG format.Note: To conserve resources and limit bandwidth usage, the resolution of PNG images will be capped at 1MP when transferred over WiFi. Such a limitation will be relevant only if 13MP is selected as Color Resolution. A pop-up will inform the user about the 1MP limitation when 13MP+PNG configuration is selected. |
Custom request header settingsAdded in 2.4.2
Under the section Settings -> Data Settings -> WiFi API -> Custom request header, the HTTP/HTTPS headers can be customized.
| Entry | App | Description |
|---|---|---|
Authorization header |
Parcel Pallet | Define the value for the Authorization HTTP/HTTPS header key. This parameter can be used to specify a Bearer Token used to authenticate and authorize access to a protected resource. |
User-Agent header |
Parcel Pallet | Define the value for the User-Agent HTTP/HTTPS header key. |
Custom headers JSON |
Parcel Pallet | Define a JSON string where a set of custom key-value HTTP/HTTPS headers can be defined. E.g.:{"p1":"a", "p2":3} |
HTTP request is configured as follows:
| Property | Value |
|---|---|
Request Method |
POST |
Content-Type |
application/json; utf-8 |
Accept |
application/json |
A response code in the range 200-299 is expected as a response.
POST /newEntry HTTP/1.1
Content-Type: application/json; utf-8
Accept: application/json
User-Agent: Dalvik/2.1.0 (Linux; U; Android 8.1.0; Scorpio Build/V008R001)
Host: 192.168.7.103:5000
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 199
{"timestamp":"2021\/02\/25 02:16:25","l":266,"w":203,"h":72,"weight":6807,"barcode":"X001SS387V","shape":"Irregular","device":"FH0402211100001","note":"QWERTY","attributes":{"batt":"false","hazmat":"true"}}
Added in 2.1.0
HTTP over TLS can be used by simply defining https as protocol in the URL of the endpoint.
If the server's SSL certificate was issued by a well-known Certificate Authority (CA), no further action is necessary.
A self-signed certificate is one that is signed with the servers own private key instead of being signed by a CA.
If the server is using a self-signed certificate, adding the certificate to the Perceptor M2 (see link) will be necessary. Failure to do so will throw the following error when the M2 is attempting to communicate with the server:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Following is an example on how to create a self-signed certificate using OpenSSL command line tool
openssl req -x509 -newkey rsa:4096 -keyout self_key.pem -out self_cert.pem -sha256 -days 365 -nodes \ -subj "/C=US/ST=California/L=San Jose/O=Qboid/OU=TestingWebService/CN=testing.qboid.ai/emailAddress=info@qboid.ai" \ -addext "subjectAltName=DNS:testing.qboid.ai"
self_cert.pem) to the M2 using the M2's Web Browser app, or from a PC over the M2's USB-C port.Settings -> Security -> Encryption & Credential -> Install from storageCertificate NameVPN and apps is selected as Credential useQBOID provides a testing www server that can be used for experimenting with the different API configurations/protocols.
The test server can be reached through a reverse proxy that's exposing the same service with different combinations of protocols and certificates. All endpoints refer to the same service, so data pushed over https will be visible on the http page and vice versa.
Disclaimer
Before using the server, please review the following:
| Protocol | Web Visualization URL | M2 Endpoint |
|---|---|---|
| HTTP | http://testing.qboid.ai:5001/ | http://testing.qboid.ai:5001/newEntry |
| HTTPS (self signed) | https://testing.qboid.ai:5002/ | https://testing.qboid.ai:5002/newEntry |
| HTTPS (public CA) | https://testing.qboid.ai:5003/ | https://testing.qboid.ai:5003/newEntry |
Web Visualization URLs can be opened with any PC or Phone browser. The page will wait for 120s for incoming data sent by any M2 device that's currently using a Testing Server Endpoint.
QR code link to HTTP Web Visualization URL
Testing server endpoints can be configured on the M2 settings in Data Settings -> API Endpoint.
Click on Use Testing Server and select the desired combination of Protocol and certificate.
For using the self-signed certificate:
Disclaimer: The code is for illustration and learning purposes only. It prioritizes simplicity over production-level robustness and should not be used in a production environment.
Code
from flask import Flask from flask import request import json app = Flask(__name__) @app.route("/newEntry", methods=['POST']) def newEntry(): data = json.loads(request.data) print("Barcode: %s Size: %ix%ix%i" % (data["barcode"], data["l"], data["w"], data["h"])) return "" if __name__ == "__main__": app.run(host = '0.0.0.0')
Output (2 dimensioning events of the same object)
Barcode: X001SS387V Size: 266x201x72
192.168.7.108 - - [24/Feb/2021 19:34:15] "POST /newEntry HTTP/1.1" 200 -
Barcode: X001SS387V Size: 267x200x72
192.168.7.108 - - [24/Feb/2021 19:36:00] "POST /newEntry HTTP/1.1" 200 -
For testing the previous code set the device endpoint to:
http://[HOST-IP]:5000/newEntry
where [HOST-IP] is the IP address of the PC running the code. E.g.: `192.168.7.100`
Code
import requests import json import random import string from datetime import datetime # To be changed according to the setup ENDPOINT = 'http://127.0.0.1:5000/newEntry' def rndString(minsize, maxSize): return ''.join(random.choices(string.ascii_uppercase + string.digits, k = random.randint(minsize, maxSize))) def createJsonEntry(): data = {} data['timestamp'] = datetime.utcnow().strftime('%Y/%m/%d %H:%M:%S') data['l'] = random.randint(10,500) data['w'] = random.randint(10,500) data['h'] = random.randint(10,500) data['weight'] = random.randint(10,50000) data['barcode'] = rndString(2,20) data['shape'] = 'Irregular' data['device'] = rndString(8,8) data['note'] = rndString(0,20) attributes = {} for i in range(random.randint(0, 4)): attributes[rndString(3,5)] = rndString(3,5) data['attributes'] = attributes strjson = json.dumps(data) # Explicitly escaping "/" since python json library is not doing it by default strjson = strjson.replace('/', '\/') return strjson if __name__ == "__main__": jsonMsg = createJsonEntry() print(jsonMsg) headers = {'content-type': 'application/json; utf-8', 'Accept' : 'application/json'} try: response = requests.post(ENDPOINT, data=jsonMsg, headers=headers) if (response.ok): print('Success') else: print('Error. Endpoint %s returned code: %i' % (ENDPOINT, response.status_code)) except Exception as e: print('Error while sending request to endpoint: %s' % ENDPOINT)
Output (Success)
{"timestamp": "2021\/02\/25 05:02:08", "l": 56, "w": 419, "h": 68, "weight": 46405, "barcode": "KPGVETAS", "shape": "Irregular", "device": "Y3S9JH1D", "note": "3RI9CKE2N", "attributes": {"FJ4": "U1HC6"}}
Success
Output (Endpoint returned an error)
{"timestamp": "2021\/02\/25 05:04:52", "l": 494, "w": 430, "h": 290, "weight": 31464, "barcode": "GE7WJ83B3PNJBN", "shape": "Irregular", "device": "DO1KF5ZI", "note": "A3KYJ", "attributes": {"SVRAJ": "HMXK"}}
Error. Endpoint http://127.0.0.1:5000/newEntry returned code: 405
Output (Endpoint unreachable)
{"timestamp": "2021\/02\/25 05:06:08", "l": 449, "w": 129, "h": 432, "weight": 2339, "barcode": "UUYXJ9Y447M", "shape": "Irregular", "device": "BO2X6TD2", "note": "B71U", "attributes": {"AF7Y": "BX44"}}
Error while sending request to endpoint: http://127.0.0.1:5000/newEntry
Code
from flask import Flask from flask import request import json app = Flask(__name__) @app.route("/newEntry", methods=['POST']) def newEntry(): print("Authorization: %s" % request.headers.get('Authorization', "")) if request.headers.get("Authorization", "") != "qboid": return "Authorization error!", 401 data = json.loads(request.data) print("User-Agent: %s" % request.headers.get('User-Agent')) print("Headers: %s" % str(dict(request.headers))) print("Barcode: %s Size: %ix%ix%i" % (data["barcode"], data["l"], data["w"], data["h"])) return "" if __name__ == "__main__": app.run(host = '0.0.0.0')
Output (Success)
Barcode: X001SS387V Size: 266x201x72
192.168.7.108 - - [13/Mar/2023 14:19:57] "POST /newEntry HTTP/1.1" 200 -
Output (Wrong Authorization)
192.168.7.108 - - [13/Mar/2023 14:19:21] "POST /newEntry HTTP/1.1" 401 -
For testing the previous code set the device end point to:
http://[HOST-IP]:5000/newEntry
where [HOST-IP] is the IP address of the PC running the code. E.g.: `192.168.7.100`
And set the Authorization header to:
qboid
Added in 2.3.0
This is an Android Intent based API where a local application can invoke the QBOID M2 applications and optionally retrieve a dimensioning record.
The API is designed to work with Android Applications following the Android's Intent paradigm, but it also provides equivalent functionalities even to Web Applications running in a common Web Browser.
QBOID M2 applications can be invoked using an explicit intent with the following parameters:
| Item and Parcel Dimensioning App | Pallet Dimensioning App | |
|---|---|---|
| Package | ai.qboid.glapp |
ai.qboid.palletsize |
| Class | ai.qboid.glapp.DimActivity |
ai.qboid.palletsize.PalletActivity |
Optionally, an action and a JSON configuration for that action can be specified in the Extra Bundle
| Field | Format | Description |
|---|---|---|
action |
string (optional) |
Action to be performed by the app. If not specified, the app will simply open the main activity |
config |
JSON string (optional) |
Configuration to be used for the requested action. If not specified, default values would be used as specified in the documentation for each action |
dimM2 applications will be invoked for acquiring a single Dimensioning Record. The workflow will return to the caller once the user confirms/saves the data for the current item. Application settings, upload queue and history won't be accessible until the action is completed or aborted.
| Field | Format | Default | App | Description |
|---|---|---|---|---|
target |
string |
queue |
Parcel Pallet | Possible values are queue, callback or none. queue: The record will be added to the standard QBOID application upload queue. The default WiFi API settings will be used. The upload may not happen immediately, depending on settings and network availabilitycallback: The record won't be added to the QBOID application upload queue nor the History but it will instead be sent immediately to the endpoint and the application won't return to the caller until the record is fully transmitted or an error occurrednone: The record won't be added to the QBOID application upload queue nor to the History. |
endpoint |
string |
As defined in Settings > Data Settings > WiFi API > API endpoint |
Parcel Pallet | Used when target=callback. Define the URL for the HTTP/HTTPS endpoint. |
usejpg |
boolean |
true |
Parcel Pallet | Used when target=callback. If true, JPEG format will be used for image, imagecolor and imageseg fields, PNG will be used otherwise. Additional constraints apply depending on the other Acquisition and WiFi API settings. (See WiFi API Settings for more info) |
enableimage |
boolean |
false |
Parcel Pallet | Used when target=callback. Enable/Disable the image field for the callback to the endpoint. |
enableimageseg |
boolean |
false |
Parcel Pallet | Used when target=callback. Enable/Disable the imageseg field for the callback to the endpoint |
enableimagecolor |
boolean |
false |
Parcel Pallet | Used when target=callback. Enable/Disable the imagecolor field for the callback to the endpoint |
headerauthorization |
string |
As defined in Settings > Data Settings > WiFi API > API endpoint > Custom request header |
Parcel Pallet | Used when target=callback. Defines the value for the Authorization HTTP header field. |
headeruseragent |
string |
As defined in Settings > Data Settings > WiFi API > API endpoint > Custom request header |
Parcel Pallet | Used when target=callback. Defines the value for the User-Agent HTTP header field. |
headercustom |
JSON object |
As defined in Settings > Data Settings > WiFi API > API endpoint > Custom request header |
Parcel Pallet | Used when target=callback. Defines a set of key-value pairs of strings for sending custom HTTP header fields.Example: {"Proxy-Authorization":"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==","Cache-Control":"no-cache"} |
prefill |
JSON object |
null |
Parcel | Added in 2.6.6Pre-fills the specified fields in the M2 interface upon opening. The required format is a JSON object structured according to the Dimensioning Record. Although the full dimensioning record can be provided, only the following fields will be processed:
The accepted data types and units for each field are consistent with those defined in the Dimensioning Record. |
gridimage_enable |
boolean |
true |
Pallet | Used when target=callback. If set to true, image and imagecolor will display all recorded angles in a single image using a grid format. If set to false, only the first viewpoint will be used. |
gridimage_printdim |
boolean |
true |
Pallet | Used when target=callback and gridimage_enable=true. If set to true, measured dimensions will be displayed on each viewpoint in the grid. They are positioned in the top left corner of each viewpoint. |
gridimage_customunits |
boolean |
false |
Pallet | Used when target=callback, gridimage_enable=true, and gridimage_printdim=true. If set to true, the dimensions reported inside image will reflect the current unit, precision, and rounding settings. Otherwise, dimensions will be reported as per the standard API format (mm), with no rounding and a precision of 1. |
static_attributes |
JSON object |
As defined in Settings > Data Settings > Static attributes |
Parcel Pallet | Added inIf defined, used in place of the Static attributes already defined in the app settings. Example: {"operator":"Bob","warehouse":"warehouse-1"} |
When the caller Activity is resumed, an Intent Result will be returned with a resultCode.
If the user returned to the caller activity without scanning an item (i.e.: Some of the mandatory fields needed for record creation, as indicated by the application configuration, are missing), the returned values would be resultCode = 0 and a null Intent.
If the user correctly scanned an item, the caller will receive a resultCode = -1 and an Intent with the Extra Bundle containing the result of the task.
Returned Extra Bundle Structure
| Field | Format | Description |
|---|---|---|
res |
int |
0: If an object record creation task succeeded <0: If an error occurred |
sent |
boolean |
Present only when target is set to callback. If true, the dimensioning record has been successfully sent via the API, false otherwise. |
record |
JSON string |
The Dimensioning Record as defined here, with the difference that the image fields (i.e.:image,imagecolor and imageseg) will contain the absolute path on the sdcard for the images instead of the base64 encoding of the content. Note: The WiFi API settings and the action configuration will not affect the content of the record. The path to the images will always be returned, if available, in PNG format. |
Example of record field in the Extra Bundle
{ "timestamp": "2022\/10\/05 23:06:45", "l": 319, "w": 203, "h": 421, "barcode": "TBA065003602504", "shape": "Irregular", "device": "FH0402211700146", "note": "Comment", "attributes": { "ovpk": "true", "batt": "false", "frgl": "true", "hazmat": "true" }, "image": "\/sdcard\/qboid\/data\/2022_10_05\/2022_10_05_23_06_15\/Frames\/result_img_1.png", "imageseg": "\/sdcard\/qboid\/data\/2022_10_05\/2022_10_05_23_06_15\/Frames\/color0_segmented_1.png", "imagecolor": "\/sdcard\/qboid\/data\/2022_10_05\/2022_10_05_23_06_15\/Frames\/color0_1.png" }
Following is a description of the most common use cases for the Android Intent API integration and how they can be implemented using the provided API. All these workflows apply to both the Parcel and the Pallet App.
Scenario
The customer uses several apps and has his own Launcher Application. Once the M2 Dimensioning App is opened, multiple sequences may be collected, settings may be changed, and data offloading can be performed over WiFi using the settings defined in the application.
Implementation
The M2 Dimensioning App will be launched with an Intent with no action and no other Extra defined in the Bundle.
Scenario
The main workflow is directed by a Third Party app that may require the collection of dimensions, picture and/or other metadata for an item during the workflow. The local Third Party app doesn't require immediate feedback, and there is no hard constraint on when the data needs to be sent over WiFi. Instead, we want to be able to buffer the network requests in case of a slow network or no connection.
Implementation
We want to invoke an intent with action=dim and a config with target=queue (Note: queue is the default value so the config field can be omitted).
The M2 API settings needs to be configured with the correct endpoint.
The endpoint needs to be able to associate the received record to the correct entry in the workflow.
Scenario
The main workflow is directed by a Third Party app that may require the collection of dimensions, picture and/or other metadata for an item during the workflow. The app would need to use and/or display the information generated by the M2 Dimensioning App as soon as it regains focus. Additionally, the caller App wants to bypass the default Qboid configuration and keep the acquired sequences away from the standard Upload Queue and History defined in the Qboid app.
Implementation
We want to invoke an intent with action=dim and we need to properly construct the config attribute.
If the caller is an Android app, the target would generally be set to none (or callback if a remote endpoint has to be notified) and the Dimensioning Record would be read from the Intent Returned Value.
If the caller is a Web App, the target has to be set to callback and the proper endpoint should be set to the wanted URL. Generally the endpoint will be defined on the same Web Server that is running the Web Application and would contain the information to identify the current request and/or session. Once the focus is returned to the Web App, it will take care of retrieving the Dimensioning Record for the Web Server.
This section provides sample code on how to invoke the Explicit Intent, and how to receive the Intent Result for the different typical use cases. Examples are in Java using Activity.onActivityResult. Equivalent code may be written in Kotlin and/or using ActivityResultContracts. Changing the package and class name is sufficient to make it work with the Parcel App or the Pallet App.
A) Open an M2 Dimensioning App
For Invoking the M2 Dimensioning App with no action we can simply define the Explicit Intent and call it with startActivity
// A) Open the M2 Item and Parcel Dimensioning App Intent intent = new Intent(); ComponentName cName = new ComponentName("ai.qboid.glapp", "ai.qboid.glapp.DimActivity"); // For the Pallet Dimensioning App use: // ComponentName cName = new ComponentName("ai.qboid.palletsize", "ai.qboid.palletsize.PalletActivity"); intent.setComponent(cName); context.startActivity(intent);
B) Trigger a single dimensioning operation
An action=dim can be set as Extra simply adding intent.putExtra("action", "dim"); to the previous example
// B) Trigger a single dimensioning operation with the M2 Item and Parcel Dimensioning App Intent intent = new Intent(); ComponentName cName = new ComponentName("ai.qboid.glapp", "ai.qboid.glapp.DimActivity"); // For the Pallet Dimensioning App use: // ComponentName cName = new ComponentName("ai.qboid.palletsize", "ai.qboid.palletsize.PalletActivity"); intent.setComponent(cName); intent.putExtra("action", "dim"); // Select dim as action context.startActivity(intent);
C) Request a dimensioning operation and retrieve the result
Setting the target=none for the config field can be done using a JSONObject instance.
Additionally, for receiving the result, the M2 Dimensioning Activity needs to be started with startActivityForResult, that will take a requestCode argument to help identify the request that triggered the result being returned.
onActivityResult will be invoked when the called Activity is closed and it will contain the data generated by the M2 Dimensioning App.
// C) Request a dimensioning operation and retrieve the result with the M2 Item and Parcel Dimensioning App Intent intent = new Intent(); ComponentName cName = new ComponentName("ai.qboid.glapp", "ai.qboid.glapp.DimActivity"); // For the Pallet Dimensioning App use: // ComponentName cName = new ComponentName("ai.qboid.palletsize", "ai.qboid.palletsize.PalletActivity"); intent.setComponent(cName); intent.putExtra("action", "dim"); // Select dim as action // Add config field with target->none to the Intent Extras JSONObject json = new JSONObject(); try { json.put("target", "none"); intent.putExtra("config", json.toString()); } catch (JSONException e) {} // Start activity and wait for result context.startActivityForResult(intent, REQUEST_CODE); // REQUEST_CODE can be any number and it's used to identify the result. //! Process the result obtained once the called Activity is closed protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE && data != null && resultCode == -1){ String recordJson = data.getStringExtra("record"); // -- PROCESS HERE THE DIMENSIONING RECORD -- } }
A Web Application can launch an Android Application with an Intent as described in: Android Intents with Chrome.
The M2 Applications are configured to receive a BROWSABLE Intent with scheme intentapi on their activities.
Below are a few examples on how to invoke the Explicit Intent, and how to receive the Intent Result for the different typical use cases. Examples are provided in Python with Flask + Javascript. Equivalent code may be written in different programming languages and different Web Server. The examples illustrate the usage for the Parcel App, but the same applies to the Pallet App.
A) Open the M2 Item and Parcel Dimensioning App
This use case may be simply implemented adding a link (or a button) pointing to the following URI: intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;end
HTML example:
<a href="intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;end"> A) Open the M2 Item and Parcel Dimensioning App</a>
B) Trigger a single dimensioning operation
The URI from the previous example can be altered using the syntax for defining String extras to configure dim as action: S.action=dim
HTML example:
<a href="intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;S.action=dim;end"> B) Trigger a single dimensioning operation</a>
C) Request a dimensioning operation and retrieve the result
Web Applications are unable to receive the Intent Returned value when running in a Web Browser, so a result can be obtained instructing the M2 Dimensioning App on how to send data to the Web Server and then retrieving that information when the Browser Tab is resumed. This workflow can be split in the following steps (diagram):
The goal would be to generate an intent URI with a configuration where target=callback and the endpoint is set to a value generated by the current Web Application.
Here is an example of the config JSON string where the server is running at the address http://192.168.1.164:5000 and /callback is the endpoint handling the record coming from M2 Dimensioning App:
{"target":"callback","endpoint":"http://192.168.1.164:5000/callback"}
The config String would then need to be converted to the correct URI encoding using a library like urllib, obtaining something like:
%7B%22target%22%3A%22callback%22%2C%22endpoint%22%3A%22http%3A//192.168.1.164%3A5000/callback%22%7D
The encoded config can then be added to the URI in the previous example prepending it with the attribute: S.config=. The final result would look like:
intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;S.action=dim;S.config=%7B%22target%22%3A%22callback%22%2C%22endpoint%22%3A%22http%3A//192.168.1.164%3A5000/callback%22%7D;end
Following is the sample Python + Flask code for generating the URI:
config = '{"target":"callback","endpoint":"%scallback"}' % request.url_root intent = "intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;S.action=dim;S.config=%s;end" % urllib.parse.quote(config)
Once the user confirms/saves the data for the current item, the dimensioning record will be sent to the endpoint as defined by the caller. The application would then close and return the focus to the browser running the Web App.
Once the Tab with the Web Application is resumed, the server needs to be queried to retrieve the information sent by the M2 Dimensioning App. This can be done by fetching the data from an endpoint on the server as soon as the Web Document becomes visible again.
Following is a javascript example that detects when document.visibilityState is changed to visible and invokes the update() function that will be implemented to retrieve the information from the server.
<script> document.addEventListener("visibilitychange", () => { if (document.visibilityState === 'visible') update(); }); function update() { // Query the server for the result } </script>
Web Application use case C) diagram
|
We are presenting here an example in Python with Flask + Javascript, summarizing the 3 uses cases discussed before both for the Parcel App and the Pallet App. It includes code to be used in an HTML template and the endpoints to be defined in Flask. We finally provide a fully self-contained Python app.
Disclaimer: The code is for illustration and learning purposes only. It prioritizes simplicity over production-level robustness and should not be used in a production environment.
HTML Template (main.html)
A), B), and C) for the Parcel AppD), E), and F)) for the Pallet App/size when the Tab is resumed and print the result in a <pre> element.<a href="intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;end">A) (Parcel) Open M2 Dimensioning App</a> <hr> <a href="intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;S.action=dim;end">B) (Parcel) Trigger a single dimensioning operation</a> <hr> <a href="{{intent_c}}">C) (Parcel) Request a dimensioning operation and retrieve the result</a> <hr> <a href="intent://#Intent;scheme=intentapi;package=ai.qboid.palletsize;end">D) (Pallet) Open M2 Dimensioning App</a> <hr> <a href="intent://#Intent;scheme=intentapi;package=ai.qboid.palletsize;S.action=dim;end">E) (Pallet) Trigger a single dimensioning operation</a> <hr> <a href="{{intent_f}}">F) (Pallet) Request a dimensioning operation and retrieve the result</a><br> <pre id="result"></pre> <script> document.addEventListener("visibilitychange", () => { if (document.visibilityState === 'visible') update(); }); function update() { var xhttp = new XMLHttpRequest(); xhttp.open("GET", "size", true); xhttp.onload = function () { let responseTxt = xhttp.responseText; document.getElementById('result').innerHTML = responseTxt; }; xhttp.onerror = function () { document.getElementById('result').innerHTML = "Request Error"; }; xhttp.send(); } </script>
Python Web Server
main.html at the endpoint /./callback and stores it locally./size.latestResponse = "---" @app.route("/", methods=['GET']) def main(): config = '{"target":"callback","endpoint":"%scallback"}' % request.url_root intent_c = "intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;S.action=dim;S.config=%s;end" % urllib.parse.quote(config) intent_f = "intent://#Intent;scheme=intentapi;package=ai.qboid.palletsize;S.action=dim;S.config=%s;end" % urllib.parse.quote(config) res = render_template("main.html", intent_c = intent_c, intent_f = intent_f) return res @app.route("/callback", methods=['POST']) def callback(): global latestResponse data = json.dumps(json.loads(request.data), indent = 4) latestResponse = data return "" @app.route("/size", methods=['GET']) def size(): global latestResponse retSize = latestResponse latestResponse = "---" return retSize
Note: In this example, for simplicity, the case where multiple sessions can be established with the server is not supported. In an actual production implementation the /callback and /size endpoints would require additional variables to properly identify a device and/or session.
Full python code with embedded HTML
from flask import Flask, render_template_string,request,render_template import json import urllib.parse app = Flask(__name__) main_html = """ <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <h3>Perceptor Android API Test</h3> <a href="intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;end">A) (Parcel) Open M2 Dimensioning App</a> <hr> <a href="intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;S.action=dim;end">B) (Parcel) Trigger a single dimensioning operation</a> <hr> <a href="{{intent_c}}">C) (Parcel) Request a dimensioning operation and retrieve the result</a> <hr> <a href="intent://#Intent;scheme=intentapi;package=ai.qboid.palletsize;end">D) (Pallet) Open M2 Dimensioning App</a> <hr> <a href="intent://#Intent;scheme=intentapi;package=ai.qboid.palletsize;S.action=dim;end">E) (Pallet) Trigger a single dimensioning operation</a> <hr> <a href="{{intent_f}}">F) (Pallet) Request a dimensioning operation and retrieve the result</a><br> <pre id="result"></pre> <script> document.addEventListener("visibilitychange", () => { if (document.visibilityState === 'visible') update(); }); function update() { var xhttp = new XMLHttpRequest(); xhttp.open("GET", "size", true); xhttp.onload = function () { let responseTxt = xhttp.responseText; document.getElementById('result').innerHTML = responseTxt; }; xhttp.onerror = function () { document.getElementById('result').innerHTML = "Request Error"; }; xhttp.send(); } </script> </body> </html> """ latestResponse = "---" @app.route("/", methods=['GET']) def main(): config = '{"target":"callback","endpoint":"%scallback"}' % request.url_root intent_c = "intent://#Intent;scheme=intentapi;package=ai.qboid.glapp;S.action=dim;S.config=%s;end" % urllib.parse.quote(config) intent_f = "intent://#Intent;scheme=intentapi;package=ai.qboid.palletsize;S.action=dim;S.config=%s;end" % urllib.parse.quote(config) res = render_template("main.html", intent_c = intent_c, intent_f = intent_f) return res @app.route("/callback", methods=['POST']) def callback(): global latestResponse data = json.dumps(json.loads(request.data), indent = 4) latestResponse = data return "" @app.route("/size", methods=['GET']) def size(): global latestResponse retSize = latestResponse latestResponse = "---" return retSize if __name__ == "__main__": app.run(host = '0.0.0.0')
QBOID provides a testing server with http and https endpoints running a live version of the sample Web Application described in this section.
Disclaimer
Before using the server, please review the following:
Testing Server URLs
| Protocol | URL | QR code |
|---|---|---|
| HTTP | http://testing.qboid.ai:5001/api | |
| HTTPS | https://testing.qboid.ai:5003/api |
Added in 2.5.0
The purpose of this functionality is to facilitate the export and import of M2 settings, also referred to as preferences, allowing them to be easily applied across multiple devices as well.
To export the configuration of an M2 DImensionig App, the specific button placed under Settings -> Import/Export Settings -> Export settings to local file can be used. Once clicked, this will save the current device configuration to the file /sdcard/qboid/preferences.json, for the Parcel App, and to the file /sdcard/qboid/pallet_preferences.json for the Pallet App.
There are two main workflows to import a previously saved configuration into an M2 device:
Settings -> Import/Export Settings and click the Import settings from local file button.Choose File to select the JSON file that needs to be encoded as a QR code. If the file is a valid configuration, a QR code will be displayed on the webpage. The generated QR code can then be downloaded as a PNG or SVG image. The configuration can be loaded into the M2 device simply scanning the QR code from the main M2 application window or from Settings -> Import/Export Settings.When exporting to a file or generating a QR code, only the settings that differ from the default values are exported.
The behavior when importing preferences is determined by the restoredefault entry in the JSON:
true, all preferences NOT defined in the QR code/file will be reset to their default values.false, preferences not defined in the QR code/file will remain unchanged.There is one exception to this rule for the configuration of Attributes (i.e., the 4 soft keys defined on the home screen). This exception will be discussed in more detail in the next section.
Since version 2.6.6, with the introduction of different types for the four attributes on the home screen, more advanced logic has been introduced for exporting and importing attribute configurations to fully support the use case where a QR code is used to reconfigure all attribute entries on the fly.
Here’s how the logic works:
When exporting an attribute, if any value (key, type, or values) has been changed from the default, the entire configuration of that attribute will be exported, regardless of whether some values are still set to default.
When importing an older QR code/file (version <2.6.6), if any attribute is modified, the other preferences for that attribute that were not explicitly set will be restored to their default values.
| Name | Type | Default value | Min version | App | Description |
|---|---|---|---|---|---|
allow_empty_trashSettings pathApplication settings → Data Settings → History → Allow Empty Trash |
boolean |
false |
2.5.0 |
Parcel Pallet | Allow to empty the trash from records |
api_content_typeSettings pathApplication settings → Data Settings → WiFi API → Custom request header → Content Type |
string |
2.6.7 |
Parcel Pallet | The content type to use when sending an API request | |
api_custom_headersSettings pathApplication settings → Data Settings → WiFi API → Custom request header → Custom headers JSON |
JSON string |
2.5.0 |
Parcel Pallet | The custom headers (specified as JSON key-value entries) to be used when sending an API request | |
api_endpointSettings pathApplication settings → Data Settings → WiFi API → API endpoint |
string |
http://192.168.7.100:5000/newEntry |
2.5.0 |
Parcel Pallet | The API endpoint to upload the results |
api_header_authorizationSettings pathApplication settings → Data Settings → WiFi API → Custom request header → Authorization header |
string |
2.5.0 |
Parcel Pallet | The Authorization header to use when sending an API request | |
api_header_useragentSettings pathApplication settings → Data Settings → WiFi API → Custom request header → User-Agent header |
string |
2.5.0 |
Parcel Pallet | The User-Agent header to use when sending an API request | |
api_upload_format_jpegSettings pathApplication settings → Data Settings → WiFi API → Use JPEG format |
boolean |
true |
2.5.0 |
Parcel Pallet | Upload all the images in JPEG format when sending a record via API |
api_upload_gridSettings pathApplication settings → Data Settings → Grid layout output → Enable grid layout output |
boolean |
true |
3.2.0 |
Pallet | Upload images containing all the pallet PoV as a grid when sending a record via API |
api_upload_grid_custom_dimsSettings pathApplication settings → Data Settings → Grid layout output → Custom units for grid layout |
boolean |
false |
3.2.0 |
Pallet | In the PoV grid images use the local application unit to display measured dimensions |
api_upload_grid_show_dimsSettings pathApplication settings → Data Settings → Grid layout output → Add dimensions to grid layout |
boolean |
true |
3.2.0 |
Pallet | In the PoV grid images display the measured dimensions |
api_upload_img_colorSettings pathApplication settings → Data Settings → WiFi API → Upload color image |
boolean |
false |
2.5.0 |
Parcel Pallet | Upload the color image when sending a record via API |
api_upload_img_resultSettings pathApplication settings → Data Settings → WiFi API → Upload result image |
boolean |
false |
2.5.0 |
Parcel Pallet | Upload the result image when sending a record via API |
api_upload_img_segSettings pathApplication settings → Data Settings → WiFi API → Upload segmented image |
boolean |
false |
2.5.0 |
Parcel Pallet | Upload the segmented image when sending a record via API |
api_upload_resultsSettings pathApplication settings → Data Settings → WiFi API → Realtime WMS upload |
boolean |
false |
2.5.0 |
Parcel Pallet | Realtime WMS upload after a completed dimensioning |
api_upload_timeoutSettings pathApplication settings → Data Settings → WiFi API → Upload timeout |
numeric |
5 |
2.5.0 |
Parcel Pallet | The timeout in seconds to be used when sending an API request |
api_upload_unmeteredSettings pathApplication settings → Data Settings → WiFi API → Upload on unmetered connections only |
boolean |
false |
2.5.7 |
Parcel Pallet | Upload on unmetered connections only |
attribute1_keySettings pathApplication settings → Data Settings → Configure Attributes → Attribute 1 → Key |
string |
2.5.0 |
Parcel Pallet | The key of the first attribute | |
attribute1_show_valuesSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 1 → Show Values |
boolean |
false |
2.5.0 |
Parcel Pallet | Show the values of the first attribute |
attribute1_typeSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 1 → Type |
string |
softkey |
2.6.6 |
Parcel Pallet | The type of the first attribute. Allowed values: softkey, list, number |
attribute1_valuesSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 1 → Values |
string |
2.5.0 |
Parcel Pallet | The values of the first attribute | |
attribute2_keySettings pathApplication settings → Data Settings → Configure Attributes → Attribute 2 → Key |
string |
2.5.0 |
Parcel Pallet | The key of the second attribute | |
attribute2_show_valuesSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 2 → Show Values |
boolean |
false |
2.5.0 |
Parcel Pallet | Show the values of the second attribute |
attribute2_typeSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 2 → Type |
string |
softkey |
2.6.6 |
Parcel Pallet | The type of the second attribute. Allowed values: softkey, list, number |
attribute2_valuesSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 2 → Values |
string |
2.5.0 |
Parcel Pallet | The values of the second attribute | |
attribute3_keySettings pathApplication settings → Data Settings → Configure Attributes → Attribute 3 → Key |
string |
2.5.0 |
Parcel Pallet | The key of the third attribute | |
attribute3_show_valuesSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 3 → Show Values |
boolean |
false |
2.5.0 |
Parcel Pallet | Show the values of the third attribute |
attribute3_typeSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 3 → Type |
string |
softkey |
2.6.6 |
Parcel Pallet | The type of the third attribute. Allowed values: softkey, list, number |
attribute3_valuesSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 3 → Values |
string |
2.5.0 |
Parcel Pallet | The values of the third attribute | |
attribute4_keySettings pathApplication settings → Data Settings → Configure Attributes → Attribute 4 → Key |
string |
2.5.0 |
Parcel Pallet | The key of the fourth attribute | |
attribute4_show_valuesSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 4 → Show Values |
boolean |
false |
2.5.0 |
Parcel Pallet | Show the values of the fourth attribute |
attribute4_typeSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 4 → Type |
string |
softkey |
2.6.6 |
Parcel Pallet | The type of the fourth attribute. Allowed values: softkey, list, number |
attribute4_valuesSettings pathApplication settings → Data Settings → Configure Attributes → Attribute 4 → Values |
string |
2.5.0 |
Parcel Pallet | The values of the fourth attribute | |
auto_cleanup_daysSettings pathApplication settings → Data Settings → Data cleanup → Automatic data cleanup → `` |
numeric |
30 |
2.5.0 |
Parcel Pallet | Duration to retain data in days |
auto_cleanup_enabledSettings pathApplication settings → Data Settings → Data cleanup → Automatic data cleanup → `` |
boolean |
false |
2.5.0 |
Parcel Pallet | Enable automatic cleanup, to automatically delete sequences older than a specified value |
auto_pose_detectionSettings pathApplication settings → Workflow Settings → Flow and Interface → Automated pose detection |
boolean |
true |
3.2.0 |
Pallet | Automated pose detection |
barcode_caseSettings pathApplication settings → Data Settings → Others → Convert scanned barcodes |
string |
0 |
2.6.9 |
Parcel Pallet | Convert scanned barcodes case mode. Possible values: 0 (Unchanged), 1 (UPPERCASE), 2 (lowercase) |
barcode_mandatorySettings pathApplication settings → Workflow Settings → Scan Constraints → Mandatory Barcode |
boolean |
false |
2.6.0 |
Parcel Pallet | Acquiring barcode is mandatory to save a result |
btscale_enabledSettings pathApplication settings → Workflow Settings → Bluetooth Scale → Settings → Use Bluetooth Scale |
boolean |
false |
2.5.0 |
Parcel | Use bluetooth scale |
btscale_name_prefixSettings pathApplication settings → Workflow Settings → Bluetooth Scale → Settings → `` |
string |
Adam |
2.5.0 |
Parcel | The prefix for the name of the bluetooth scale |
color_resolutionSettings pathApplication settings → Developers Settings → Color Resolution |
string |
2 |
2.5.0 |
Parcel | The color resolution to use. Possible values: 2 (0.3MP), 3 (13MP) |
compute_alpha_channelSettings pathApplication settings → Data Settings → Acquisition → Compute Alpha Channel |
boolean |
false |
2.5.0 |
Parcel | Compute the alpha channel on the segmented images |
csv_output_utcSettings pathApplication settings → Data Settings → USB API → CSV Filename UTC |
boolean |
false |
2.5.0 |
Parcel | UTC time zone is used for the CSV file naming |
custom_field_enabledSettings pathApplication settings → Data Settings → Custom Fields → `` |
boolean |
false |
2.5.0 |
Parcel Pallet | Enable the custom field. If disabled, the Sum is computed |
custom_field_formulaSettings pathApplication settings → Data Settings → Custom Fields → `` |
string |
L,W,H,+,+ |
2.5.0 |
Parcel Pallet | Formula for computing the custom field. The formula is in Reverse Polish Notation (RPN) using a , delimiter |
custom_field_labelSettings pathApplication settings → Data Settings → Custom Fields → `` |
string |
@string/sum |
2.5.0 |
Parcel Pallet | Label for the custom field. Note: Strings exceeding 3 characters in length may affect UI formatting |
dimensioning_mandatorySettings pathApplication settings → Workflow Settings → Scan Constraints → Mandatory dimensioning |
boolean |
true |
2.5.2 |
Parcel Pallet | A successful dimensioning is mandatory to save a result |
note_mandatorySettings pathApplication settings → Workflow Settings → Scan Constraints → Mandatory Note Field |
boolean |
false |
2.6.7 |
Parcel Pallet | Note field is mandatory to save a result |
note_only_numbersSettings pathApplication settings → Data Settings → Others → Use numpad for Note entry |
boolean |
false |
2.5.0 |
Parcel Pallet | Only numbers can be inserted into the Note entry |
preview_timeoutSettings pathApplication settings → Workflow Settings → Flow and Interface → Preview display timeout |
string |
8000 |
2.5.0 |
Parcel Pallet | The preview timeout in milliseconds. Possible values: 5000, 8000, 10000, 20000, 30000 |
resume_pose_changeSettings pathApplication settings → Workflow Settings → Flow and Interface → Resume on pose change |
boolean |
true |
3.2.0 |
Pallet | Resume the stream on pose change |
rt_feedback_ar_planeSettings pathApplication settings → Workflow Settings → Flow and Interface → Enable Plane Overlay |
boolean |
true |
2.6.5 |
Parcel | Enable the AR plane overlay feedback |
rt_feedback_hapticSettings pathApplication settings → Workflow Settings → Flow and Interface → Haptic feedback |
boolean |
true |
2.6.5 |
Parcel | Enable the haptic feedback to alert the operator of suboptimal scanning conditions |
rt_feedback_profileSettings pathApplication settings → Workflow Settings → Flow and Interface → Real-time feedback |
string |
1 |
2.6.5 |
Parcel | The real-time feedback profile. Possible values: 1 (Standard), 2 (Warning only) and 0 (Unrestricted) |
s1_auto_resetSettings pathS1 Settings → S1 Settings → Auto reset when removed |
boolean |
true |
3.0.0 |
Parcel | [S1] Clear data when the object is removed from the scale |
s1_auto_uploadSettings pathS1 Settings → S1 Settings → Auto data upload |
string |
1 |
3.0.0 |
Parcel | [S1] Controls when to automatically upload a result. Possible values: 0 (Disabled), 1 (On scan), 2 (On item removed) |
s1_barcode_ignore_line_endingSettings pathS1 Settings → S1 Settings → Barcode ignore line ending |
boolean |
true |
3.0.1 |
Parcel | [S1] Specifies whether line endings (\\n) should be ignored when using the external barcode scanner. |
s1_barcode_timeoutSettings pathS1 Settings → S1 Settings → Timed sizing after barcode event |
string |
1000 |
3.0.0 |
Parcel | [S1] Sets how long after a barcode scanning event the sequence will automatically trigger. Possible values in ms: -1 (Disabled), 0, 500, 1000, 1500, 2000, 3000, 4000, 5000 |
s1_require_connected_scannerSettings pathS1 Settings → S1 Settings → Require barcode scanner |
boolean |
false |
3.0.0 |
Parcel | [S1] Specifies whether a barcode scanner is required to be connected for operation. |
s1_trigger_soundSettings pathS1 Settings → S1 Settings → Emit sound on sizing event |
boolean |
true |
3.0.0 |
Parcel | [S1] Emit a sound when a sizing event is completed |
s1_voi_margin_backSettings pathS1 Settings → S1 Settings → Volume Of Interest → VOI margin back |
numeric |
50 |
3.0.1 |
Parcel | [S1] Margin in mm, from the pole next to the scale, that delimits the back boundary of the Volume of Interest |
s1_voi_margin_frontSettings pathS1 Settings → S1 Settings → Volume Of Interest → VOI margin front |
numeric |
150 |
3.0.1 |
Parcel | [S1] Margin in mm, from the scale plate, that delimits the front boundary of the Volume of Interest |
s1_voi_margin_leftSettings pathS1 Settings → S1 Settings → Volume Of Interest → VOI margin left |
numeric |
150 |
3.0.1 |
Parcel | [S1] Margin in mm, from the scale plate, that delimits the left boundary of the Volume of Interest |
s1_voi_margin_rightSettings pathS1 Settings → S1 Settings → Volume Of Interest → VOI margin right |
numeric |
150 |
3.0.1 |
Parcel | [S1] Margin in mm, from the scale plate, that delimits the right boundary of the Volume of Interest |
scene_validation_enabledSettings pathApplication settings → Workflow Settings → Flow and Interface → Enable scene validation |
boolean |
true |
3.2.0 |
Pallet | Enable the scene validation |
show_tipsSettings pathApplication settings → Workflow Settings → Flow and Interface → Display Tips |
boolean |
true |
2.5.0 |
Parcel | Display the tips to the user |
show_title_barSettings pathApplication settings → Workflow Settings → Flow and Interface → Show title bar |
boolean |
true |
2.5.0 |
Parcel | Display the title bar of the application |
size_precisionSettings pathApplication settings → Data Settings → Displayed dimensions → Dimension precision |
string |
1 |
2.5.0 |
Parcel Pallet | Parcel: Dimension precision. Possible values: 10, 1, 0.5, 0.25, 0.1, 0.01 Pallet: Dimension precision. Possible values: 10, 1, 0.5, 0.25, 0.1 |
size_roundingSettings pathApplication settings → Data Settings → Displayed dimensions → Dimension rounding method |
string |
0 |
2.5.0 |
Parcel Pallet | Default rounding method. Possible values: 0 (nearest), 1 (truncate down), 2 (clamp up) |
size_unitSettings pathApplication settings → Data Settings → Displayed dimensions → Default dimension unit |
string |
mm |
2.5.0 |
Parcel Pallet | Default dimension unit. Possible values: mm, in, cm |
static_attributesSettings pathApplication settings → Data Settings → Static attributes |
JSON string |
3.2.1 |
Parcel Pallet | Attributes, defined as key-value pairs, that are added to the list of dynamic attributes defined via UI | |
upload_on_barcodeSettings pathApplication settings → Workflow Settings → Flow and Interface → Upload on barcode event |
boolean |
false |
2.5.2 |
Parcel Pallet | Upload the current record immediately after a barcode event |
weight_mandatorySettings pathApplication settings → Workflow Settings → Scan Constraints → Mandatory Weight |
boolean |
false |
2.6.0 |
Parcel Pallet | Acquiring weight is mandatory to save a result |
weight_precisionSettings pathApplication settings → Data Settings → Displayed weight → Weight precision |
string |
1 |
2.5.0 |
Parcel Pallet | Parcel: Weight precision. Possible values: 10, 1, 0.5, 0.25, 0.1, 0.01 Pallet: Weight precision. Possible values: 10, 1, 0.1 |
weight_roundingSettings pathApplication settings → Data Settings → Displayed weight → Weight rounding method |
string |
0 |
2.5.0 |
Parcel Pallet | Weight rounding method. Possible values: 0 (nearest), 1 (truncate down), 2 (clamp up) |
weight_unitSettings pathApplication settings → Data Settings → Displayed weight → Default weight unit |
string |
Parcel gPallet Kg |
2.5.0 |
Parcel Pallet | Default weight unit. Possible values: g, Kg, lb, oz |
wifi_manual_uploadSettings pathApplication settings → Data Settings → History → Allow Manual Upload |
boolean |
false |
2.5.0 |
Parcel Pallet | Allow to manually upload records from Pending/History |
{ "jsonver": 0, "app": "parcel", "restoredefault": true, "prefs": [] }
{ "jsonver": 0, "app": "pallet", "restoredefault": true, "prefs": [] }
{ "jsonver": 0, "app": "parcel", "restoredefault": false, "prefs": [ { "key": "size_unit", "minver": "2.5.0", "type": "string", "value": "in" }, { "key": "size_precision", "minver": "2.5.0", "type": "string", "value": "0.25" }, { "key": "weight_unit", "minver": "2.5.0", "type": "string", "value": "lb" } ] }
{ "jsonver": 0, "app": "pallet", "restoredefault": false, "prefs": [ { "key": "size_unit", "minver": "2.5.0", "type": "string", "value": "in" }, { "key": "size_precision", "minver": "2.5.0", "type": "string", "value": "0.25" }, { "key": "weight_unit", "minver": "2.5.0", "type": "string", "value": "lb" } ] }
{ "jsonver": 0, "app": "parcel", "restoredefault": false, "prefs": [ { "key": "api_endpoint", "minver": "2.5.0", "type": "string", "value": "https:\/\/testing.qboid.ai:5003\/newEntry" }, { "key": "api_upload_img_result", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "api_upload_img_seg", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "api_upload_img_color", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "api_upload_results", "minver": "2.5.0", "type": "boolean", "value": true } ] }
{ "jsonver": 0, "app": "pallet", "restoredefault": false, "prefs": [ { "key": "api_endpoint", "minver": "2.5.0", "type": "string", "value": "https:\/\/testing.qboid.ai:5003\/newEntry" }, { "key": "api_upload_img_result", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "api_upload_img_seg", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "api_upload_img_color", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "api_upload_results", "minver": "2.5.0", "type": "boolean", "value": true } ] }
{ "jsonver": 0, "app": "parcel", "restoredefault": false, "prefs": [ { "key": "attribute1_key", "minver": "2.5.0", "type": "string", "value": "CASE" }, { "key": "attribute1_show_values", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "attribute1_values", "minver": "2.5.0", "type": "string", "value": "CASE,0,EACH,0" }, { "key": "attribute2_key", "minver": "2.5.0", "type": "string", "value": "3481" }, { "key": "attribute2_values", "minver": "2.5.0", "type": "string", "value": ",0,true,1,false,2" }, { "key": "attribute3_key", "minver": "2.5.0", "type": "string", "value": "FRAGILITY" }, { "key": "attribute3_show_values", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "attribute3_values", "minver": "2.5.0", "type": "string", "value": "F-1,0,F-2,0,F-3,0" } ] }
{ "jsonver": 0, "app": "pallet", "restoredefault": false, "prefs": [ { "key": "attribute1_key", "minver": "2.5.0", "type": "string", "value": "CASE" }, { "key": "attribute1_show_values", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "attribute1_values", "minver": "2.5.0", "type": "string", "value": "CASE,0,EACH,0" }, { "key": "attribute2_key", "minver": "2.5.0", "type": "string", "value": "3481" }, { "key": "attribute2_values", "minver": "2.5.0", "type": "string", "value": ",0,true,1,false,2" }, { "key": "attribute3_key", "minver": "2.5.0", "type": "string", "value": "FRAGILITY" }, { "key": "attribute3_show_values", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "attribute3_values", "minver": "2.5.0", "type": "string", "value": "F-1,0,F-2,0,F-3,0" } ] }
{ "jsonver": 0, "app": "parcel", "restoredefault": false, "prefs": [ { "key": "auto_cleanup_days", "minver": "2.5.0", "type": "numeric", "value": 90 }, { "key": "auto_cleanup_enabled", "minver": "2.5.0", "type": "boolean", "value": true } ] }
{ "jsonver": 0, "app": "pallet", "restoredefault": false, "prefs": [ { "key": "auto_cleanup_days", "minver": "2.5.0", "type": "numeric", "value": 90 }, { "key": "auto_cleanup_enabled", "minver": "2.5.0", "type": "boolean", "value": true } ] }
{ "jsonver": 0, "app": "parcel", "restoredefault": false, "prefs": [ { "key": "btscale_enabled", "minver": "2.5.0", "type": "boolean", "value": true } ] }
{ "jsonver": 0, "app": "parcel", "restoredefault": false, "prefs": [ { "key": "custom_field_enabled", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "custom_field_formula", "minver": "2.5.0", "type": "string", "value": "W,H,+,2,*" }, { "key": "custom_field_label", "minver": "2.5.0", "type": "string", "value": "GRH" } ] }
{ "jsonver": 0, "app": "pallet", "restoredefault": false, "prefs": [ { "key": "custom_field_enabled", "minver": "2.5.0", "type": "boolean", "value": true }, { "key": "custom_field_formula", "minver": "2.5.0", "type": "string", "value": "W,H,+,2,*" }, { "key": "custom_field_label", "minver": "2.5.0", "type": "string", "value": "GRH" } ] }
{ "jsonver": 0, "app": "parcel", "restoredefault": false, "prefs": [ { "key": "preferences_import_qr_ask", "minver": "2.5.0", "type": "boolean", "value": false } ] }
{ "jsonver": 0, "app": "pallet", "restoredefault": false, "prefs": [ { "key": "preferences_import_qr_ask", "minver": "2.5.0", "type": "boolean", "value": false } ] }