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.

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.