Trigger workflow and maintain workflow state

I would like to trigger a workflow update_inventory.toml in thin edge 1.6.1 when a message is published on a MQTT broker topic.
Is there way to directly trigger a workflow when a message is published or do I have to trigger the workflow publishing to the following?
te/+/+/+/+/cmd/+/+.

In addition I would like to publish an event in the workflow update_inventory.toml when e.g. the fragment c8y_Hardware changes. What is the best way to maintain the previous value of c8y_Hardware.type?

file system, tedge config get/set …

Currently there isn’t an out of the box way to trigger a workflow from arbitrary topics (e.g. such as events).

For now, you’ll have to send the command yourself (to the /cmd/ topic related to the workflow).

In the future, this should be a good use-case for the tedge-flows, which allows you to write a flow (which contains SmartFunctions), to handle the logic, however we’re still working on the feature and it is not ready to be used as of now.

1 Like

And how is it recommended to store a kind of status?
I want to avoid that a workflow performs steps a second time.
Should I publish a retained message on a mqtt topic?

In addition I would like to publish an event in the workflow update_inventory.toml when e.g. the fragment c8y_Hardware changes. What is the best way to maintain the previous value of c8y_Hardware.type?

Sorry I didn’t fully read this part before.

You have the following options:

  • Store in the file system somewhere (it place needs to be owned by the tedge user so it has read/write permissions to it)
  • Store in the MQTT broker on a topic (e.g. myapp/internal/data) as a retained message

tedge config get/set is reserved for thin-edge.io configuration, and can not be used for a key/value store.

@Christof_Strack I suspect we jumped into the solution part too quickly without fully understanding the problem at hand.

Are you able to provide a bit more details on what problem you’re trying to solve?

The process steps I want to achieve are as follows:

  1. when thin-edge registers it receives hardware information about its type: type_01 or type_02.
  2. this information is only available on the device
  3. the information needs to be added to the twin in Cumulocity
  4. publish an event c8y_TriggerSoftwareDownloadEvent to trigger the software download

The event in step 4. must not be sent multiple times, only once.
I followed the approach to store this as retained message on the broker:

[update_hardware_specification]
script = '''sh -c '
tedge mqtt pub -q 1 -r te/device/main///twin/c8y_Hardware "{\"type\": \"${.payload.type}\", \"serial_number\": \"${.payload.serial_number}\"}";
tedge mqtt pub -q 1 -r workflow/update_hardware_info/status "{\"type\": \"${.payload.type}\", \"serial_number\": \"${.payload.serial_number}\"}"
'
'''
on_success = "publish_software_download_event"

And check before if this is necessary:

[check]
script = "sh -c 'output=$(tedge mqtt sub workflow/update_hardware_info/status --count 1 --retained-only --duration 100ms --no-topic --log-level WARN 2>&1); echo \"${output}\" | grep -q \"serial_number\"'"
on_success = { status = "already_updated", reason = "already updated"}
on_error = { status = "update_hardware_specification", reason = "update hardware and serial number"}

[already_updated]
action = "proceed"
on_success = "successful"

[update_hardware_specification]
script = '''sh -c '
tedge mqtt pub -q 1 -r te/device/main///twin/c8y_Hardware "{\"type\": \"${.payload.type}\", \"serial_number\": \"${.payload.serial_number}\"}";
tedge mqtt pub -q 1 -r workflow/update_hardware_info/status "{\"type\": \"${.payload.type}\", \"serial_number\": \"${.payload.serial_number}\"}"
'
'''
on_success = "publish_software_download_event"

[publish_software_download_event]
script = '''sh -c '
tedge mqtt pub -q 1  c8y/s/us "400,c8y_TriggerSoftwareDownloadEvent, \"Trigger Software Download\"";
'
'''
on_success = "successful"

Yeah that workflow looks more or less ok to me.

Though once you start doing more complicated logic (as you have here), I would recommend creating a shell script which is called from the workflow as it will make the whole thing much easier to test and maintain.

#!/bin/sh
set -eu

ACTION="$1"
shift

update_hardware_specification() {
   echo "do something"
}

case "$ACTION" in
   update_hardware_specification)
     update_hardware_specification "$@"
     ;;

   # ... add remaining workflow states.
esac

Then from your workflow you just call into the script using the current state as the subcommand etc.