Previous
ML training client API
Triggers can alert you by email or webhook when the following events occur:
Triggers support the following attributes:
Name | Type | Required? | Description |
---|---|---|---|
name | string | Required | The name of the trigger |
event | object | Required | The trigger event object, which contains the following fields:
|
notifications | object | Required | The notifications object, which contains the following fields:
|
The following template demonstrates the form of a JSON configuration for a trigger that alerts when data syncs to the Viam cloud:
"triggers": [
{
"name": "<trigger name>",
"event": {
"type": "part_data_ingested",
"data_ingested": {
"data_types": ["binary", "tabular", "file", "unspecified"]
}
},
"notifications": [
{
"type": "<webhook|email>",
"value": "<webhook URL or email address>",
"seconds_between_notifications": <number of seconds>
}
]
}
]
The conditional
object for the conditional_data_ingested
trigger type includes the following attributes:
Name | Type | Required? | Description |
---|---|---|---|
data_capture_method | string | Required | The method of data capture to trigger on. Example: sensor:<name-of-component>:Readings . |
conditions | object | Optional | Conditions that, when true, fire the trigger. Evaluated each time data syncs from the linked component. When this object is empty or not present, the trigger fires each time data syncs from the linked component. Options:
|
The operator
attribute supports the following values:
Name | Description |
---|---|
lt | less than |
gt | greater than |
lte | less than or equal to |
gte | greater than or equal to |
eq | equal to |
neq | not equal to |
regex | matches regular expression |
The following template demonstrates the form of a JSON configuration for a conditional trigger:
"triggers": [
{
"name": "<trigger name>",
"event": {
"type": "conditional_data_ingested",
"conditional": {
"data_capture_method": "<component>:<name-of-component>:<method>",
"conditions": {
"evals": [
{
"operator": "<lt|gt|lte|gte|eq|neq|regex>",
"value": <object, string, bool, regex, or int>
}
]
}
}
},
"notifications": [
{
"type": "<webhook|email>",
"value": "<webhook URL or email address>",
"seconds_between_notifications": <number of seconds>
}
]
}
]
The following condition defines a trigger that fires based on the value of the cpu
field of synced data:
"conditions": {
"evals": [
{
"operator": "gt",
"value": {
"cpu": 50
}
}
]
}
The following sensor reading fires the trigger, since 80 > 50
is true
:
{
"readings": {
"cpu": 80
}
}
The following condition defines a trigger that fires based on a value nested in the coordinate.latitude
field of synced data:
"conditions": {
"evals": [
{
"operator": "lt",
"value": {
"coordinate": {
"latitude": 50
}
}
}
]
}
The following sensor reading fires the trigger, since 40 < 50
is true
:
{
"readings": {
"coordinate": {
"latitude": 40
}
}
}
When an event occurs, Viam sends a HTTP request to the URL you specified for the trigger:
Trigger type | HTTP Method |
---|---|
part_data_ingested | POST |
conditional_data_ingested | POST |
part_online | GET |
part_offline | GET |
The request includes the following headers:
Header Key | Description | Trigger types |
---|---|---|
Org-Id | The ID of the organization that triggered the request. | all |
Organization-Name | The name of the organization that triggered the request. | part_online , part_offline |
Location-Id | The location of the machine that triggered the request. | all |
Location-Name | The location of the machine that triggered the request. | part_online , part_offline |
Part-Id | The part of the machine that triggered the request. | all |
Machine-Name | The name of the machine that triggered the request. | part_online , part_offline |
Robot-Id | The ID of the machine that triggered the request. | all |
The request body includes the following data:
Data Key | Description | Trigger types |
---|---|---|
component_name | The name of the component for which data was ingested. | part_data_ingested , conditional_data_ingested |
component_type | The type of component for which data was ingested. | part_data_ingested , conditional_data_ingested |
method_name | The name of the method from which data was ingested. | part_data_ingested , conditional_data_ingested |
min_time_received | Indicates the earliest time a piece of data was received. | part_data_ingested |
max_time_received | Indicates the latest time a piece of data was received. | part_data_ingested |
method_name | The name of the method that triggered the request. | conditional_data_ingested |
machine_name | The name of the machine that triggered the request. | part_data_ingested , conditional_data_ingested |
location_name | The location of the machine that triggered the request. | part_data_ingested , conditional_data_ingested |
org_name | The name of the organization that triggered the request. | part_data_ingested , conditional_data_ingested |
file_id | The id of the file that was ingested. | part_data_ingested |
trigger_condition | The condition that triggered the request. | conditional_data_ingested |
data | The ingested sensor data. Includes metadata with received_at and requested_at timestamps and data in the form map[string]any . | part_data_ingested , conditional_data_ingested (sensor data) |
If you are using a cloud function or lambda to process the request from viam-server
, you can use this template.
The following example function prints the received headers:
from flask import Flask, request
app = Flask(__name__)
@app.route("/", methods=['GET', 'POST'])
def trigger():
headers = request.headers
data = {}
if request.data:
data = request.json
payload = {
"Org-Id": headers.get('org-id', 'no value'),
"Organization-Name": headers.get('organization-name', '') or
data.get('org_name', 'no value'),
"Location-Id": headers.get('location-id', 'no value'),
"Location-Name": headers.get('location-name', '') or
data.get('location_name', 'no value'),
"Part-Id": headers.get('part-id', 'no value'),
"Part-Name": headers.get('part-name', 'no value'),
"Robot-Id": headers.get('robot-id', 'no value'),
"Machine-Name": headers.get('machine-name', '') or
data.get('machine_name', 'no value'),
"Component-Type": data.get('component_type', 'no value'),
"Component-Name": data.get('component_name', 'no value'),
"Method-Name": data.get('method_name', 'no value'),
"Min-Time-Received": data.get('min_time_received', 'no value'),
"Max-Time-Received": data.get('max_time_received', 'no value'),
"Data-Type": data.get('data_type', 'no value'),
"File-Id": data.get('file_id', 'no value'),
"Trigger-Condition": data.get("trigger_condition", 'no value'),
"Data": data.get('data', 'no value')
}
print(payload)
return payload
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
import functions_framework
import requests
import time
@functions_framework.http
def hello_http(request):
headers = request.headers
data = {}
if request.data:
data = request.json
payload = {
"Org-Id": headers.get("org-id", "no value"),
"Organization-Name": headers.get("organization-name", "")
or data.get("org_name", "no value"),
"Location-Id": headers.get("location-id", "no value"),
"Location-Name": headers.get("location-name", "")
or data.get("location_name", "no value"),
"Part-Id": headers.get("part-id", "no value"),
"Part-Name": headers.get("part-name", "no value"),
"Robot-Id": headers.get("robot-id", "no value"),
"Machine-Name": headers.get("machine-name", "")
or data.get("machine_name", "no value"),
"Component-Type": data.get("component_type", "no value"),
"Component-Name": data.get("component_name", "no value"),
"Method-Name": data.get("method_name", "no value"),
"Min-Time-Received": data.get("min_time_received", "no value"),
"Max-Time-Received": data.get("max_time_received", "no value"),
"Data-Type": data.get("data_type", "no value"),
"File-Id": data.get('file_id', "no value"),
"Trigger-Condition": data.get("trigger_condition", "no value"),
"Data": data.get('data', "no value")
}
print(payload)
return 'Received headers: {}'.format(payload)
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!