JSON Automation Script
Prerequisites
Before you start writing a JSON automation script, please make sure you have obtained the necessary trait information by calling the QueryDeviceSupportedScriptAutomationConfigRequest API. For details, see Query Device Traits Available for Automation.
Standard Structure
The standard structure of a JSON automation script is shown below, including metadata and automations:
| Parameter | Type | Required | Description |
|---|---|---|---|
| metadata | Object | ✗ | Metadata of the automation operation, including automation name, description, and variable definitions. |
| metadata.name | String | ✗ | Name of the automation. |
| metadata.description | String | ✗ | Description of the automation. |
| metadata.scope | Array of DeviceProperty | ✗ | List of device property variables. |
| automations | Array of Object | ✓ | Array of automations, containing one or more automation objects. |
| automations.name | String | ✗ | Automation name. |
| automations.starters | Array of Starter | ✓ | List of starters (triggers). It must include at least one. |
| automations.condition | Object | ✗ | Execution condition; see Condition for details. |
| automations.actions | Array of Action | ✓ | List of actions to be executed when the automation is triggered. The list must include at least one action; The actions will be executed sequentially. |
Starter
A starter is a condition used to trigger automation. Starter types are as follows:
| Type | Description |
|---|---|
| PropertyEvent | This starter fires the automation only when a device property change meets specific conditions. |
| TimeSchedule | This starter fires the automation at a specified time only. |
| Manual | This starter means the automation is triggered manually by the user. |
PropertyEvent
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "property.event". |
| source | Datasource | ✓ | The device property data source to be monitored. |
| is | Dynamic | ✗ | Checks whether the data is equal to a specific value. |
| isNot | Dynamic | ✗ | Checks whether the data is not equal to a specific value. |
| greaterThan | Dynamic | ✗ | Checks whether the data is greater than a specific value. |
| greaterThanOrEqualTo | Dynamic | ✗ | Checks whether the data is greater than or equal to a specific value. |
| lessThan | Dynamic | ✗ | Checks whether the data is less than a specific value. |
| lessThanOrEqualTo | Dynamic | ✗ | Checks whether the data is less than or equal to a specific value. |
| for | Duration | ✗ | The duration for which the comparison condition must remain continuously satisfied (e.g., "30min", "1hour10min20sec"). |
| suppressFor | Duration | ✗ | The duration that must elapse after a trigger before it can be triggered again. |
Comparison operator restrictions:
isandisNotcannot be used at the same time.lessThanandlessThanOrEqualTocannot be used at the same time.greaterThanandgreaterThanOrEqualTocannot be used at the same time.
Comparison Operator Types
The value for comparison operators (is, isNot, greaterThan, etc.) supports the following three types:
-
Literal: Basic types such as Boolean, Number, or String.
Example:
// Boolean
"is": true
"is": false
// Number
"greaterThan": 25
"lessThanOrEqualTo": 100.5
// String
"is": "on"
"isNot": "offline" -
Variable reference: Reference to a variable defined in
metadata.scope, type DataRef.Example:
"is": {
"type": "data.ref",
"from": "/metadata/scope",
"select": {
"by": "name",
"value": "targetTemp"
}
} -
Device property reference: Directly comparison with another device property value.
Parameter Type Required Description type String ✓ Must be "device.property". deviceId String ✓ Device ID. functionCode String ✓ Function code. endpointId Integer ✓ Endpoint ID. traitCode String ✓ Trait code. Example:
"is": {
"type": "device.property",
"deviceId": "sensor002",
"endpointId": 1,
"functionCode": "TemperatureMeasurement",
"traitCode": "MeasuredValue"
}
TimeSchedule
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "time.schedule". |
| cron | String | (Either this or at) | Cron expression. |
| at | String | (Either this or cron) | Specific time, see Time for details. |
| timezone | String | ✗ | Specify the time zone using a valid IANA time zone identifier (e.g., "Asia/Shanghai") to ensure the scheduled task runs at the expected time zone. If not provided, Aqara Studio's current time zone will be used by default. |
Manual
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "manual". |
| name | String | ✓ | Your custom name. |
Example:
{
"type": "manual",
"name": "Go Home"
}
Condition
A condition is used to make judgments before perform an action. Only after the starter (trigger) is activated will the system evaluate whether the condition is met. If the condition passes, subsequent actions will proceed; otherwise, the operation will not be performed.
The types of Condition include:
| Type | Description |
|---|---|
| AndCondition | Triggers the action only when all sub-conditions are met. |
| OrCondition | Triggers the action when any one of the sub-conditions is met. |
| NotCondition | Inverts the result of a single sub-condition. |
| PropertyState | Checks the current state of a device property. |
| TimeBetween | Checks whether the current time is within a specified range. |
AndCondition
This condition triggers the action only when all sub-conditions are satisfied.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "and". |
| conditions | Array of Condition | ✓ | List of sub-conditions (at least two). |
Example:
{
"type": "and",
"conditions": [
{
"type": "property.state",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "roomTemp"
}
},
"greaterThan": 25
},
{
"type": "property.state",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "humidity"
}
},
"lessThan": 60
}
]
}
OrCondition
This condition triggers the action when any one of the sub-conditions is met.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "or". |
| conditions | Array of Condition | ✓ | List of sub-conditions (at least two required). |
Example:
{
"type": "or",
"conditions": [
{
"type": "property.state",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "motionSensor1"
}
},
"is": true
},
{
"type": "property.state",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "motionSensor2"
}
},
"is": true
}
]
}
NotCondition
This condition negates the result of a single sub-condition.
| Field | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "not". |
| condition | Condition | ✓ | The condition to be negated. |
Example:
{
"type": "not",
"condition": {
"type": "property.state",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "vacationMode"
}
},
"is": true
}
}
PropertyState
This condition is used to determine whether the current value of a specific property of a device meets the specified comparison condition.
| Field | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "property.state". |
| source | Datasource | ✓ | The datasource of the device property to check. |
| is | Dynamic | ✗ | Checks if the data is equal to a specific value. |
| isNot | Dynamic | ✗ | Checks if the data is not equal to a specific value. |
| greaterThan | Dynamic | ✗ | Checks if the data is greater than a specific value. |
| greaterThanOrEqualTo | Dynamic | ✗ | Checks if the data is greater than or equal to a specific value. |
| lessThan | Dynamic | ✗ | Checks if the data is less than a specific value. |
| lessThanOrEqualTo | Dynamic | ✗ | Checks if the data is less than or equal to a specific value. |
| for | Duration | ✗ | The duration for which the comparison condition must remain continuously satisfied (e.g., "30min", "1hour10min20sec"). |
You should specify at least one comparison operator.
Example:
- Basic Comparison A
- Basic Comparison B
- Comparison with Duration
{
"type": "property.state",
"source": {
"type": "device.property",
"deviceId": "light001",
"endpointId": 1,
"functionCode": "OnOff",
"traitCode": "OnOff"
},
"is": true
}
{
"type": "property.state",
"source": {
"type": "device.property",
"deviceId": "light001",
"endpointId": 1,
"functionCode": "TemperatureMeasurement",
"traitCode": "MeasuredValue"
},
"greaterThan": 2800
}
{
"type": "property.state",
"source": {
"type": "device.property",
"deviceId": "sensor001",
"endpointId": 1,
"functionCode": "TemperatureMeasurement",
"traitCode": "MeasuredValue"
},
"greaterThan": 2800,
"for": "5min"
}
TimeBetween
This condition is used to check whether the current time falls within a specified range.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "time.between". |
| after | String | ✓ | Start time, see Time for details. |
| before | String | ✓ | End time, see Time for details. |
Example:
{
"type": "time.between",
"after": "08:00",
"before": "22:00"
}
Action
An action is executed after the automation is triggered and the conditions are satisfied. Each Action describes a specific behavior to perform, such as writing a trait value or or adding a delay.
The types of actions include:
| Type | Description |
|---|---|
| TraitWrite | Write a value to a device trait. |
| Delay | Set a delay duration. |
TraitWrite
This action writes a value to a device trait.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "device.trait.write". |
| functionCode | String | ✓ | Function code. |
| traitCode | String | ✓ | Trait code. |
| targets | Array of Object | ✓ | List of target endpoints. |
| targets[].deviceId | String | ✓ | Device ID. |
| targets[].endpointIds | Array of Integer | ✓ | List of endpoint IDs. |
| value | Dynamic | ✓ | The value to be written to the trait. The type of this parameter is related to the trait type. For details, see Value Type Description. |
Value Types
| Trait Type | Value Type | Example |
|---|---|---|
| Boolean | true / false / "toggle" | true |
| Numeric | Number | 80 or 25.5 |
| Enum | String / Number | "cool" or 1 |
| String | String | "hello" |
Example:
- Turn On Light
- Set Brightness
- Set Color Temperature
{
"type": "device.trait.write",
"functionCode": "Switch",
"traitCode": "OnOff",
"targets": [
{
"deviceId": "light001",
"endpointIds": [1, 2]
},
{
"deviceId": "light002",
"endpointIds": [2, 3]
}
],
"value": true
}
{
"type": "device.trait.write",
"functionCode": "LevelControl",
"traitCode": "CurrentLevel",
"targets": [
{
"deviceId": "light001",
"endpointIds": [2]
},
{
"deviceId": "light002",
"endpointIds": [3]
}
],
"value": 80
}
{
"type": "device.trait.write",
"functionCode": "ColorControl",
"traitCode": "ColorTemperatureMireds",
"targets": [
{
"deviceId": "light001",
"endpointIds": [1]
}
],
"value": 300
}
Delay
This action is used to set a delay duration.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "delay". |
| for | Duration | ✓ | The duration to delay. |
Example:
{
"type": "delay",
"for": "20sec"
}
Datasource
Datasource is a generic structure used to reference a device property or a variable. There are two types: DeviceProperty (device property) and DataRef (variable reference).
DeviceProperty
This object is used to directly reference a specific property of a device.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "device.property". |
| deviceId | String | ✓ | Device ID. |
| functionCode | String | ✓ | Function code (e.g., OnOff, LevelControl). |
| endpointId | Integer | ✓ | Endpoint ID. |
| traitCode | String | ✓ | Trait code (e.g., OnOff, CurrentLevel). |
| name | String | ✗ | Variable name. It must be provided when defined in metadata.scope. |
DataRef
This object is used to reference a variable defined in metadata.scope.
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | String | ✓ | Must be "data.ref". |
| from | String | ✗ | Target path. Must be "/metadata/scope". It can be omitted as it defaults to this value. |
| select | Object | ✓ | Selection expression to specify the variable to reference. |
| select.by | Object | ✓ | Selection method. Must be "name". |
| select.value | Object | ✓ | Variable name (i.e., the string defined in scope.name). |
Cron
The structure of a Cron expression is: second minute hour day month weekday year (in order), detailed as follows:
| Position | Field | Allowed Values | Special Characters |
|---|---|---|---|
| 1 | Second | 0-59 | * / |
| 2 | Minute | 0-59 | * / |
| 3 | Hour | 0-23 | * / |
| 4 | Day of month | 1-31 | , * ? |
| 5 | Month | 1-12 | , - * |
| 6 | Day of week |
| , * ? |
| 7 | Year | Four digits | , * |
Special Characters
| Special Character | Meaning | Example Explanation |
|---|---|---|
* | All values | Using * in the minute field means "every minute" |
? | No specific value | When you want to specify either day-of-month or day-of-week, but don't care about the other. For example, day field 10 and week field ? means trigger on the 10th of every month, regardless of the weekday. |
- | Range | Hour field 10-12 means “10, 11 and 12 o’clock” |
, | Additional values | Weekday field 1,3,5 means “Monday, Wednesday and Friday” |
/ | Step (increment) | Second field 0/15 means "at 0, 15, 30, and 45 seconds", 5/15 means "at 5, 20, 35, 50 seconds"; day field 1/3 means "every 3 days starting from the 1st of the month"; can be used with *, such as */15 meaning "every 15 units" |
The following examples can help you better understand how to use Cron expressions:
| Cron Expression | Meaning |
|---|---|
0 0 2 * * ? * | Fire at 2:00 AM every day (regardless of day of week, ? means "no specific value" for weekday) |
0 0 9 ? * 2 * | Fire at 9:00 AM every Tuesday (? for day, trigger only on weekday 2: Tuesday) |
0 0 0 1 * ? * | Fire at midnight on the 1st of every month (regardless of day of week, ? in weekday field) |
0 */5 * * * ? * | Fire every 5 minutes (any day, ? means no specific weekday) |
0 0/15 9-17 * * ? * | Fire every 15 minutes from 9:00 AM to 5:00 PM each day (? means all weekdays) |
0 0 1 1,10,20 * ? * | Fire at 1:00 AM on the 1st, 10th, and 20th of each month (? for weekday) |
0 0 9 ? * 2,4 * | Fire at 9:00 AM every Tuesday and Thursday (? for day, triggers on weekday 2 and 4) |
0 0 0 1 1 ? 2026 | Fire at midnight on January 1, 2026 (? for weekday) |
0 0 0/3 * * ? * | Fire every 3 hours, starting at midnight each day (? means no specific weekday) |
Time
Time represents a specific point in the day and supports two types: Clock Time and Solar Time.
Clock Time
You can use either 24-hour format or AM/PM format.
- 24-hour format:
Format Example Description HH:mm 13:00 13:00 (1:00 PM) HH:mm:ss 13:00:01 13:00:01 (1:00:01 PM, seconds are optional) H:mm 8:30 8:30 (8:30 AM) - AM/PM format:
Format Example Description h:mm am/pm 0:30 am 12:30 AM (midnight thirty) h:mm am/pm 7:30 pm 7:30 PM (evening) h:mm:ss am/pm 8:00:00 am 8:00:00 AM (morning)
Solar Time
Solar time refers to the time based on sunrise or sunset. You can add or subtract an offset (Duration) to precisely set the trigger moment.
| Format | Example | Description |
|---|---|---|
| sunrise | sunrise | The time when the Sun rises |
| sunset | sunset | The time when the Sun sets |
| sunrise+Duration | sunrise+30min | 30 minutes after sunrise |
| sunrise-Duration | sunrise-1hour | 1 hour before sunrise |
| sunset+Duration | sunset+30min | 30 minutes after sunset |
| sunset-Duration | sunset-1hour | 1 hour before sunset |
Duration
Duration represents a time length and is used in the following fields:
delay.for: The waiting time for device delayed control.property.event.for: The duration for which the comparison condition must remain continuously satisfiedproperty.event.suppressFor: The duration that must elapse after a trigger before it can be triggered again.property.state.for: Checks whether a state has remained for a specific time length.
Supported time units:
| Time Unit | Keyword | Example |
|---|---|---|
| Hour | hour | 1hour |
| Minute | min | 30min |
| Second | sec | 20sec |
You can combine multiple units above in the order of hour, min, sec, as shown below:
| Example | Description |
|---|---|
| 1hour10min20sec | 1 hour 10 minutes 20 seconds |
| 1hour30min | 1 hour 30 minutes |
| 10min30sec | 10 minutes 30 seconds |
Complete Examples
Here are three examples of JSON automation scripts:
- Air Conditioner and Temperature Sensor Linkage
- Light Control with Motion Sensor
- Multi-condition Scene Control
Air Conditioner and Temperature Sensor Linkage
The following example shows how to automatically turn on the air conditioner and set it to cooling mode when the temperature exceeds 28°C for 5 minutes.
{
"metadata": {
"name": "Air Conditioner and Temperature Sensor Linkage",
"scope": [
{
"name": "roomTemp",
"type": "device.property",
"deviceId": "temp_sensor_001",
"endpointId": 1,
"functionCode": "TemperatureMeasurement",
"traitCode": "MeasuredValue"
}
]
},
"automations": [
{
"name": "Turn on air conditioner when temperature is high",
"starters": [
{
"type": "property.event",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "roomTemp"
}
},
"greaterThan": 2800,
"for": "5min",
"suppressFor": "1hour"
}
],
"condition": {
"type": "time.between",
"after": "08:00",
"before": "23:00"
},
"actions": [
{
"type": "device.trait.write",
"functionCode": "Switch",
"traitCode": "OnOff",
"targets": [
{
"deviceId": "lumi.xxxxx",
"endpointIds": [3]
}
],
"value": true
},
{
"type": "device.trait.write",
"functionCode": "Thermostat",
"traitCode": "SystemMode",
"targets": [
{
"deviceId": "lumi.xxxxx",
"endpointIds": [1]
}
],
"value": "cool"
},
{
"type": "device.trait.write",
"functionCode": "Thermostat",
"traitCode": "OccupiedCoolingSetpoint",
"targets": [
{
"deviceId": "ac_001",
"endpointIds": [1]
}
],
"value": 2500
}
]
}
]
}
Light Control with Motion Sensor
The following example shows turning on the light when motion is detected, and turning off the light 5 minutes after no motion is detected.
{
"metadata": {
"name": "Motion Sensor and Light",
"scope": [
{
"name": "motion",
"type": "device.property",
"deviceId": "motion_001",
"endpointId": 1,
"functionCode": "OccupancySensing",
"traitCode": "Occupancy"
}
]
},
"automations": [
{
"name": "Turn on light when motion is detected",
"starters": [
{
"type": "property.event",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "motion"
}
},
"is": true
}
],
"condition": {
"type": "time.between",
"after": "18:00",
"before": "06:00"
},
"actions": [
{
"type": "device.trait.write",
"functionCode": "Switch",
"traitCode": "OnOff",
"targets": [
{
"deviceId": "light_001",
"endpointIds": [1]
}
],
"value": true
}
]
},
{
"name": "无人关灯",
"starters": [
{
"type": "property.event",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "motion"
}
},
"is": false,
"for": "5min"
}
],
"actions": [
{
"type": "device.trait.write",
"functionCode": "Switch",
"traitCode": "OnOff",
"targets": [
{
"deviceId": "light001",
"endpointIds": [1]
}
],
"value": false
}
]
}
]
}
Multi-condition Scene Control
The following example shows: At 7:00 a.m. from Monday to Friday, if the temperature is below 20°C and the humidity is above 70%, turn on the dehumidifier and the heater.
{
"metadata": {
"name": "Morning Environment Adjustment",
"scope": [
{
"name": "temp",
"type": "device.property",
"deviceId": "sensor_001",
"endpointId": 1,
"functionCode": "TemperatureMeasurement",
"traitCode": "MeasuredValue"
},
{
"name": "humidity",
"type": "device.property",
"deviceId": "sensor_001",
"endpointId": 1,
"functionCode": "RelativeHumidityMeasurement",
"traitCode": "MeasuredValue"
}
]
},
"automations": [
{
"name": "Morning Environment Adjustment",
"starters": [
{
"type": "time.schedule",
"cron": "0 0 7 * * MON-FRI"
}
],
"condition": {
"type": "and",
"conditions": [
{
"type": "property.state",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "temp"
}
},
"lessThan": 2000
},
{
"type": "property.state",
"source": {
"type": "data.ref",
"select": {
"by": "name",
"value": "humidity"
}
},
"greaterThan": 7000
}
]
},
"actions": [
{
"type": "device.trait.write",
"functionCode": "Switch",
"traitCode": "OnOff",
"targets": [
{
"deviceId": "light001",
"endpointIds": [1]
}
],
"value": true
},
{
"type": "device.trait.write",
"functionCode": "Switch",
"traitCode": "OnOff",
"targets": [
{
"deviceId": "light001",
"endpointIds": [1]
},
{
"deviceId": "heater_001",
"endpointIds": [1]
}
],
"value": true
}
]
}
]
}