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:
- when thin-edge registers it receives hardware information about its type: type_01 or type_02.
- this information is only available on the device
- the information needs to be added to the twin in Cumulocity
- 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.