Initiate a workflow

Attributes

  • template: Name of the template of which we want the workflow
    • Required: Yes
  • include_tasks: If true, whatever is defined as a template could also be a task
    • Required: No
    • Default value: True

Output

  • WORKFLOW_EXTRACTED: The Workflow was successfully extracted from the given template
    • Payload: wf_uri can be used as a "wf" identifier in the start_workflow action
  • WORKFLOW_EXTRACTION_ERROR: No workflow could be extracted from the given template

Note: This is similar to the Task Browser component, but only fetches the workflow associated with the given template, rather than executing it separately. 

Example

The action can be used as follows:

<get_workflow_from_template id="get_workflow_from_template">
  <param name="template">NameOfTemplate</param>
</get_workflow_from_template>

Result handling:

<rule id="extracted">
   <expression><![CDATA[ #{event:command} == 'WORKFLOW_EXTRACTED']]></expression>
   <actions>
     <action id="start_workflow" type="start_workflow">
       <param name="wf">#{event:payload.wf_uri}</param>
     </action>
   </actions>
</rule>
<rule id="extraction_error">
   <expression><![CDATA[ #{event:command} == 'WORKFLOW_EXTRACTION_ERROR']]></expression>
   <actions>
     <finish_workflow id="finish_workflow">
       <output>
         <param name="wf_error" type="bool">true</param>
       </output>
     </finish_workflow>
   </actions>
</rule>

Setvar

Sets or updates the parameters of a workflow or a step.

Identifier: setvar

Elements

  • context_update: A list of parameters that should be set or updated.
    • Required: Yes
    • Default Value: Empty list
  • context_of: Defines the context scope which should be updated. By default, the currently active step will be updated.
    • Required: No
  • Default Value: Step
  • Possible values:
    • Workflow: The current active step will be updated.
    • Root: Saves the value in a way that is accessible in any workflow back to your root workflow.
    • Global: Creates a global context value that can be accessed from anywhere in the application ({global::my_value} in direct references or appcontext.global.my_value in Javascript).
    • User_session: Works similar to "global" (access with #{user_session::my_value}) but the values will be deleted when the user signs out.

Examples

Minimal

<setvar id="increase_step">
    <context_update>
        <param name="current_step">#{current_step}+1</param>
    </context_update>
</setvar>

All options

<setvar id="next_step">
    <context_of>root</context_of>
    <context_update>
        <param name="current_step_index" type="long">#{current_step}+1</param>
        <param name="step" type="object">?{context.steps[context.current_step_index]}?</param>
    </context_update>
</setvar>

Download Assets

Downloads one or more specified assets.

Identifier: download_assets

Example

<download_assets id="test">
      <asset_uris>xai:/assets/hops_02?version=1</asset_uris>
</download_assets>
<download_assets id="test">
  <list name="asset_uris" listType="UNNAMED">
      <elem>xai:/assets/hops_02?version=1</elem>
      <elem>xai:/assets/hops_01?version=1</elem>
      <elem>xai:/assets/hops_03?version=1</elem>
    </list>
</download_assets>

Timer

Sets a timer with the option to set specific delays and periods. The period or the timer ends when the step changes.

Identifier: timer

Attributes

  • command: This is sent after the timeout period ends.
    • Required: Yes
    • Default Value: Empty
  • delay: Contains the time after which the command is sent.
    • Required: Yes
    • Default Value: Empty
  • period: Contains the time interval after which the command should be sent again.
    • Required: No
    • Default Value: -1

Example

To start a timer that triggers the REFRESH event after 5 seconds (5000 ms) the first time and after that every 2 seconds (2000 ms), you could use this:

<timer id="trigger_refresh" command="REFRESH" delay="5000" period="2000"/>

Rest Request

This action is designed to retrieve JSON data over a REST API. It supports the POST and GET data request types.

Identifier: rest_request

Attributes

  • rest_url: Contains the REST API URL.
    • Possible values: REST URL
    • Required: Yes
    • Example:
"https://myfcc.com/sampledata/enginedata"
  • request_type: Contains the REST request type.
    • Possible values: "POST", "GET"
    • Required: Yes
    • Example:
"GET"
  • value_path: Contains the path to the JSON data value.
    • Required: Yes
    • Example:
"$.rpm" //check Jayway JsonPath for more examples
  • rest_params: Contains the parameters that should be passed to the REST service.
    • Possible values: MAP
    • Required: No
    • Example:
\<list name="rest_params"
listType="NAMED">

\<param name="serial"
type="string">1337\</param>
\</list>
  • repeat_every_ms: Contains the time interval in milliseconds after which, the action requests new values.
    • Possible values: Integer
    • Required: Yes
    • Example (for every 5 seconds):
5000
  • payload_path: Contains an optional path where the received value can be stored. If no path is given, the "sensor_value" will be used.
    • Possible values: String
    • Required: No
    • Example:
"sensor_value"

Examples

Let's consider a JsonPath given the following JSON structure:

[{
    "color"="blue",
    "id"=87427,
    "name"="Blueforce87427",
    "position"={
        "datetime"="2017-07-20T13: 58: 47.947513+02: 00",
        "positionX"=2722,
        "positionY"=2,
        "positionZ"=3980
    }
}{
    "color"="red",
    "id"=11111,
    "name"="Opfor11111",
    "position"={
        "datetime"="2017-07-20T13: 58: 47.947513+02: 00",
        "positionX"=3222,
        "positionY"=232,
        "positionZ"=4000
    }
}]

You can use the following JsonPath strings to retrieve data from the endpoint:

1. JsonPath:

$[0]['name']

2. Returned string:

Blueforce87427

3. JsonPath:

$[0]['position']

4. Returned string:

[{
"datetime"="2022-07-27T13:58:47.925260+02:00,
"positionX"=2722,
"positionY"= 2, 
"positionZ"= 3980
}]

5. JsonPath:

$[*] 

6. Returned string:

Whole array with both objects 

Minimal

<rest_request id="my_rest_test0">
    <param name="rest_url" type="string">https://alex.dev.ubimax.com/sampledata/enginedata</param>
    <param name="request_type" type="string">POST</param>
    <param name="value_path" type="string">$.rpm</param>
    <list name="rest_params" listType="NAMED">
        <param name="serial" type="string">1337</param>
    </list>
</rest_request>

All options

<rest_request id="my_rest_test0">
    <param name="rest_url" type="string">https://alex.dev.ubimax.com/sampledata/enginedata</param>
    <param name="request_type" type="string">POST</param>
    <param name="value_path" type="string">$.rpm</param>
    <param name="repeat_every_ms" type="string">5000</param>
    <param name="payload_path" type="string">myPayload</param>
    <list name="rest_params" listType="NAMED">
        <param name="serial" type="string">1337</param>
    </list>
</rest_request>

Send Commit Message

Sends a generic message with customizable properties to the Frontline connector. These are handled via the DefaultInspectionRequestHandler.class attribute.

Identifier: send_commit_message

Attributes

  • type: Contains the event type to switch over in the Frontline connector.
    • Possible values: String
    • Required: True
    • Default value: Empty
  • connection_timeout: Contains the timeout out in seconds.
    • Possible values: numeric_value
    • Required: False
    • Default value: 50
  • save_response: Contains the context to save the response in.
    • Possible values: Step, workflow
    • Required: False
    • Default value: Step

Elements

  • identifier: Contains the ID used for integration services (e.g. task ID).
    • Required: False
    • Default Value: "" (empty string)
  • properties: Contains the collection of parameters that can be used by the integration service.
  • Required: False
  • Default Value: [] (empty collection)

Note: Properties are internally converted to a map and their values can be a collection of recursive conversions. The final map is stored as a JSON string in the payload string of the message and primitive values such as string, numeric, and boolean are stored inside the properties map field. This makes the message very flexible when communicating with the integration service.

Response handling

There are three possible outcomes when sending a commit message:

  • Success
  • Timeout 
  • Error

A timeout occurs when no response is received after the specified time. This happens due to the message getting lost in the network or the server requiring too much time to process the result.

An error in this case generally means unexpected behaviour such as failure to send messages due to either network errors or server errors. Expected error handling (e.g., handling an invalid state in the process) is done via a successful response.

All responses generate an input event with the send_commit_message modality. The command is one of RESPONSE_OK, RESPONSE_TIMEOUT or RESPONSE_ERROR.

Messages contain a payload object that contains additional data for the response. In the case of error and timeout, the payload contains the "type" and "identifier" fields set to the same values as used in the request. This can be used to identify errors for specific requests if needed.

In the case of a success, these fields are not present but the "status" field is set to a numeric value (defined by the handler in the integration service). This value can be used to handle error cases that are expected in the process. In all cases, the "response" field contains a string defined by the integration service that can be used to differentiate the response further.

In addition to the status and response values, the integration service can define additional properties to be sent back with the event. These properties are available as context variables at the time of event handling. An example of this would be sending back an error message from the customer WMS for error handling or additional information to process the successful commit (see below for fragments of this).

Examples

<send_commit_message id="pre_task_request" type="PRE_TASK_REQUEST" connection_timeout="600">
    <properties>
        <param name="group" type="string">#{group}</param>
        <param name="aisle" type="string">#{aisle}</param>
    </properties>
</send_commit_message>
<send_commit_message id="complete_inspection" type="COMPLETE_INSPECTION" connection_timeout="1500">
  <param name="identifier">#{cockpit_id}</param>
</send_commit_message>

The value for the identifier is not valid to be set as a tag attribute – this should be possible with future iterations of the creator.

<send_commit_message id="send_asset_info" type="PHOTO" connection_timeout="60">
    <properties>
        <param name="asset_uri" type="string">#{event:payload.media_file}</param>
        <param name="order_id" type="string">?{pickOrder.name}?</param>
        <param name="group_id" type="string">?{pickOrder.groups[activeGroup].label}?</param>
        <param name="customer_reference">?{pickOrder.groups[activeGroup].picks[0].article.customerReference}?</param>
        <param name="amount" type="string">?{pickOrder.groups[activeGroup].picks[0].amountOpen}?</param>
    </properties>
</send_commit_message>

Uploading an image asset and sending a commit message with information about the uploaded asset

This example step just expects an image asset URI (media_file) as input:

<step id="send_asset" uitemplate="WAIT" persist="false" screen_lock_enabled="false" debug_mode="false">
    <actions>
        <action id="upload_media" type="trigger_upload_asset">
            <param name="asset_uri">#{media_file}</param>
            <param name="delete_after_upload" type="bool">true</param>
            <param name="upload_immediately" type="bool">true</param>
            <param name="upload_immediately_delete_on_failure" type="bool">true</param>
        </action>

        <send_commit_message id="send_asset_info" type="PHOTO" connection_timeout="200">
            <properties>
                <param name="asset_uri" type="string">#{event:payload.asset_uri}</param>
                <param name="asset_name" type="string">#{event:payload.asset_name}</param>
                <param name="asset_version" type="string">#{event:payload.asset_version}</param>
            </properties>
        </send_commit_message>

        <ui_notification id="show_nok" type="WARN">
            <duration>SHORT</duration>
            <message>Picture NOT OK</message>
        </ui_notification>

        <ui_notification id="show_upload_error" type="ERROR">
            <duration>SHORT</duration>
            <message>Media upload failed</message>
        </ui_notification>

        <ui_notification id="show_commit_error" type="ERROR">
            <duration>SHORT</duration>
            <message>Commit failed</message>
        </ui_notification>
    </actions>

    <states>
        <onresume>
            <rule id="auto_exec">
                <expression>1</expression>
                <actions>
                    <action ref="upload_media"/>
                </actions>
            </rule>
        </onresume>

        <onevent>
            <rule id="upload_ok">
                <expression>
                    <![CDATA[#{event(trigger_upload_asset):command} == 'OK']]>
                </expression>
                <actions>
                    <action ref="send_asset_info"/>
                </actions>
            </rule>
            <rule id="upload_error">
                <expression>
                    <![CDATA[#{event(trigger_upload_asset):command} == 'ERROR' || #{event(trigger_upload_asset):command} == 'NETWORK_ERROR' || #{event(trigger_upload_asset):command} == 'INTERNAL_ERROR']]>
                </expression>
                <actions>
                    <action ref="show_upload_error"/>
                    <action ref="finish"/>
                </actions>
            </rule>

            <rule id="commit_ok_ok">
                <expression>
                    <![CDATA[#{event(send_commit_message):command} == 'RESPONSE_OK' && #{event(send_commit_message):payload.response} == 'OK']]>
                </expression>
                <actions>
                    <action ref="finish_workflow"/>
                </actions>
            </rule>
            <rule id="commit_ok_nok">
                <expression>
                    <![CDATA[#{event(send_commit_message):command} == 'RESPONSE_OK' && #{event(send_commit_message):payload.response} != 'OK']]>
                </expression>
                <actions>
                    <action ref="show_nok"/>
                    <action ref="goto_take_picture"/>
                </actions>
            </rule>
            <rule id="commit_error_or_timeout">
                <expression>
                    <![CDATA[#{event(send_commit_message):command} == 'RESPONSE_ERROR' || #{event(send_commit_message):command} == 'RESPONSE_TIMEOUT']]>
                </expression>
                <actions>
                    <action ref="show_commit_error"/>
                    <action ref="goto_take_picture"/>
                </actions>
            </rule>
        </onevent>

    </states>
</step>

Handling with custom error status

<actions>
  <!-- dialog references variables set by the commit message response for error handling -->
  <ui_dialog id="sap_error" type="Error" title="Error">
    <message><![CDATA[#{sap_message}<br>Continue to '#{sap_material}/#{sap_position}'?]]></message>
    <buttons>
      <button>
        <text>ANDRRES_fw</text>
        <command>SAP_FIX</command>
        <focused>true</focused>
      </button>
      <button>
        <text>ANDRRES_bw</text>
        <command>DO_NOT_TRY_AGAIN</command>
      </button>
    </buttons>
  </ui_dialog>

<!-- more actions
  [...]
-->
</actions>

<!-- more WF code
 [...]
-->

<onevent>
  <!-- Technical success but check for SAP response -->
  <rule id="success">
    <expression><![CDATA[#{event:command} == 'RESPONSE_OK' && #{event:payload.status} == 0 ]]></expression>
    <actions>
      <ui_notification id="show_done" type="INFO">
        <duration>SHORT</duration>
        <message>#{cockpit_id} completed...</message>
      </ui_notification>
      <action ref="close_ds_task"/>
      <action ref="finish_workflow"/>
    </actions>
  </rule>

  <rule id="sap_error_in_success">
    <expression><![CDATA[#{event:command} == 'RESPONSE_OK' && #{event:payload.status} == 500 ]]></expression>
    <actions>  
      <!-- variables are automatically set when the event is handled and can be used in the action -->
      <action ref="sap_error"/>
    </actions>
  </rule>

  <rule id="unknown_error_in_success">
    <expression><![CDATA[#{event:command} == 'RESPONSE_OK' && #{event:payload.status} != 0 && #{event:payload.status} != 500 ]]></expression>
    <actions>
      <action ref="completion_error"/>
    </actions>
  </rule>

  <rule id="request_error">
    <expression><![CDATA[#{event:command} == 'RESPONSE_ERROR']]></expression>
    <actions>
      <action ref="completion_error"/>
    </actions>
  </rule>

  <rule id="request_timeout">
    <expression><![CDATA[#{event:command} == 'RESPONSE_TIMEOUT']]></expression>
    <actions>
      <action ref="completion_error"/>
    </actions>
  </rule>
</onevent>

MQTT example

<send_commit_message id="send_mqtt" type="FRONTLINE_MQTT" connection_timeout="200">
    <properties>
        <param name="mqtt" type="string"><![CDATA[?{
            var mqtt = {
                topic: "MY/TOPIC",
                content: "MY CONTENT"
            };
            var stringmqtt = JSON.stringify(mqtt);
            stringmqtt;}?]]>
        </param>
    </properties>
</send_commit_message>

Handler side

Here is an example of handling code in the connector, inside the "Inspection" request handler.

@Override
public CommitMessageResponse handleCommitMessage(CommitMessage aCommit) {
    if("COMPLETE_INSPECTION".equals(aCommit.getType())) {
        String evaluation = aCommit.getIdentifier();
        // HANDLE EVENT
        // [CODE]
        if(isSuccess) {
            log.info("Completion success!");
            return new CommitMessageResponse(aCommit, 0, "Success!");
        }
        // HANDLE ERROR
        CommitMessageResponse cmr = new CommitMessageResponse(aCommit, 500, "SAP Error!");
        cmr.addProperties("sap_message", cr.getMessage()); // 'cr' is an object specific to the custom code
        cmr.addProperties("sap_material", cr.getMaterial());
        cmr.addProperties("sap_position", cr.getPosition());
        return cmr;
    }
    // OTHER MESSAGES

The properties added in the error case will be available to the workflow when the event is handled.

Add Attachment

Adds an attachment to the task results of the current step.

Identifier: add_attachment

Note: You need to enable reporting for your component in the workflow tag. Otherwise, the action will have no effect. Here's an example of how you can do this: <workflow [...] reporting="true"></workflow>

Elements

  • type: Contains the type of attachment you want to add to the task result.
    • Required: Yes
    • Default value: Empty
  • content: Contains the content you want to add to the task result.
    • Required: False
    • Default value: Empty
  • override: Contains the value that is already saved with the given type is replaced.
    • Required: No
    • Default value: True

Default types

  • asset
  • barcode-content
  • documentation-comment
  • comment
  • question (used by the "Questionnaire" component for saving the complete question)
  • selected-answers (used by the "Questionnaire" component for saving selected answers)

Note: You can also set your own type.

Example

Minimal

<add_attachment id="add_attachment">
    <param name="type" type="string">documentation-comment</param>
    <param name="content" type="string">#{current_comment}</param>
</add_attachment>

All options

<add_attachment id="document_barcode">
    <param name="type" type="string">barcode-content</param>
    <param name="content" type="string">#{code}</param>
    <param name="override" type="bool">false</param>
</add_attachment>

Get Attachment Content

Retrieves the last attachment added for a particular attachment data type.

Identifier: get_attachment_content

Elements

  • type: Contains the type of attachment you want to retrieve from the attachments.
    • Required: Yes
    • Default value: Empty
  • write_to: Contains the name of the variable where you want to store the retrieved attachment content.
    • Required: Yes
    • Default value: Empty
  • write_if_empty: Saves the received value. If an existing value exists in the given variable, the data will be overwritten.
    • Required: No
    • Default value: True

Default types

  • asset
  • barcode-content
  • documentation-comment
  • comment
  • question (used by the "Questionnaire" component for saving the complete question)
  • selected-answers (used by the "Questionnaire" component for saving selected answers

Note: You also have the option to add your own attachment type if it is not already on the list of available types.

Examples

Minimal

<get_attachment_content id="get_attachment_content">
    <param name="type" type="string">documentation-comment</param>
    <param name="write_to" type="string">current_comment</param>
</get_attachment_content>

All options

<get_attachment_content id="get_attachment_content">
    <param name="type" type="string">documentation-comment</param>
    <param name="write_to" type="string">current_comment</param>
    <param name="write_if_empty" type="bool">true</param>
</get_attachment_content>

Module State

Used to change the state of a module. For example, you can use it to deactivate speech input recognition.

Identifier: module_state

Attributes

  • module_name: The name of the module
  • Possible values:
    • de.ubimax.andriod.speechrecognition.SpeechRecognitionModule
    • de.ubimax.andriod.client.output.SoundManager
    • de.ubimax.andriod.core.gps.GeoModule
    • de.ubimax.andriod.core.output.sound.TextToSpeechManager
    • Required: False
  • change_state_to: The state the module is supposed to enter
    • Possible values:
      • init
      • destroy
      • stop
      • pause
      • resume
      • start
    • Required: True

Example

<module_state id="resume_speech" module_name="de.ubimax.android.speechrecognition.SpeechRecognitionModule" change_state_to="resume"/>
<module_state id="pause_speech" module_name="de.ubimax.android.speechrecognition.SpeechRecognitionModule" change_state_to="pause"/>

Log Off

Logs off the client.

Identifier: logoff

Example

<logoff id="myaction"/>