Skip to main content

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:

ParameterTypeRequiredDescription
metadataObjectMetadata of the automation operation, including automation name, description, and variable definitions.
metadata.nameStringName of the automation.
metadata.descriptionStringDescription of the automation.
metadata.scopeArray of DevicePropertyList of device property variables.
automationsArray of ObjectArray of automations, containing one or more automation objects.
automations.nameStringAutomation name.
automations.startersArray of StarterList of starters (triggers). It must include at least one.
automations.conditionObjectExecution condition; see Condition for details.
automations.actionsArray of ActionList 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:

TypeDescription
PropertyEventThis starter fires the automation only when a device property change meets specific conditions.
TimeScheduleThis starter fires the automation at a specified time only.
ManualThis starter means the automation is triggered manually by the user.

PropertyEvent

ParameterTypeRequiredDescription
typeStringMust be "property.event".
sourceDatasourceThe device property data source to be monitored.
isDynamicChecks whether the data is equal to a specific value.
isNotDynamicChecks whether the data is not equal to a specific value.
greaterThanDynamicChecks whether the data is greater than a specific value.
greaterThanOrEqualToDynamicChecks whether the data is greater than or equal to a specific value.
lessThanDynamicChecks whether the data is less than a specific value.
lessThanOrEqualToDynamicChecks whether the data is less than or equal to a specific value.
forDurationThe duration for which the comparison condition must remain continuously satisfied (e.g., "30min", "1hour10min20sec").
suppressForDurationThe duration that must elapse after a trigger before it can be triggered again.
tip

Comparison operator restrictions:

  • is and isNot cannot be used at the same time.
  • lessThan and lessThanOrEqualTo cannot be used at the same time.
  • greaterThan and greaterThanOrEqualTo cannot 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.

    ParameterTypeRequiredDescription
    typeStringMust be "device.property".
    deviceIdStringDevice ID.
    functionCodeStringFunction code.
    endpointIdIntegerEndpoint ID.
    traitCodeStringTrait code.

    Example:

    "is": {
    "type": "device.property",
    "deviceId": "sensor002",
    "endpointId": 1,
    "functionCode": "TemperatureMeasurement",
    "traitCode": "MeasuredValue"
    }

TimeSchedule

ParameterTypeRequiredDescription
typeStringMust be "time.schedule".
cronString(Either this or at)Cron expression.
atString(Either this or cron)Specific time, see Time for details.
timezoneStringSpecify 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

ParameterTypeRequiredDescription
typeStringMust be "manual".
nameStringYour 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:

TypeDescription
AndConditionTriggers the action only when all sub-conditions are met.
OrConditionTriggers the action when any one of the sub-conditions is met.
NotConditionInverts the result of a single sub-condition.
PropertyStateChecks the current state of a device property.
TimeBetweenChecks whether the current time is within a specified range.

AndCondition

This condition triggers the action only when all sub-conditions are satisfied.

ParameterTypeRequiredDescription
typeStringMust be "and".
conditionsArray of ConditionList 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.

ParameterTypeRequiredDescription
typeStringMust be "or".
conditionsArray of ConditionList 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.

FieldTypeRequiredDescription
typeStringMust be "not".
conditionConditionThe 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.

FieldTypeRequiredDescription
typeStringMust be "property.state".
sourceDatasourceThe datasource of the device property to check.
isDynamicChecks if the data is equal to a specific value.
isNotDynamicChecks if the data is not equal to a specific value.
greaterThanDynamicChecks if the data is greater than a specific value.
greaterThanOrEqualToDynamicChecks if the data is greater than or equal to a specific value.
lessThanDynamicChecks if the data is less than a specific value.
lessThanOrEqualToDynamicChecks if the data is less than or equal to a specific value.
forDurationThe duration for which the comparison condition must remain continuously satisfied (e.g., "30min", "1hour10min20sec").
tip

You should specify at least one comparison operator.

Example:

{
"type": "property.state",
"source": {
"type": "device.property",
"deviceId": "light001",
"endpointId": 1,
"functionCode": "OnOff",
"traitCode": "OnOff"
},
"is": true
}

TimeBetween

This condition is used to check whether the current time falls within a specified range.

ParameterTypeRequiredDescription
typeStringMust be "time.between".
afterStringStart time, see Time for details.
beforeStringEnd 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:

TypeDescription
TraitWriteWrite a value to a device trait.
DelaySet a delay duration.

TraitWrite

This action writes a value to a device trait.

ParameterTypeRequiredDescription
typeStringMust be "device.trait.write".
functionCodeStringFunction code.
traitCodeStringTrait code.
targetsArray of ObjectList of target endpoints.
targets[].deviceIdStringDevice ID.
targets[].endpointIdsArray of IntegerList of endpoint IDs.
valueDynamicThe 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 TypeValue TypeExample
Booleantrue / false / "toggle"true
NumericNumber80 or 25.5
EnumString / Number"cool" or 1
StringString"hello"

Example:

{
"type": "device.trait.write",
"functionCode": "Switch",
"traitCode": "OnOff",
"targets": [
{
"deviceId": "light001",
"endpointIds": [1, 2]
},
{
"deviceId": "light002",
"endpointIds": [2, 3]
}
],
"value": true
}

Delay

This action is used to set a delay duration.

ParameterTypeRequiredDescription
typeStringMust be "delay".
forDurationThe 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.

ParameterTypeRequiredDescription
typeStringMust be "device.property".
deviceIdStringDevice ID.
functionCodeStringFunction code (e.g., OnOff, LevelControl).
endpointIdIntegerEndpoint ID.
traitCodeStringTrait code (e.g., OnOff, CurrentLevel).
nameStringVariable name. It must be provided when defined in metadata.scope.

DataRef

This object is used to reference a variable defined in metadata.scope.

ParameterTypeRequiredDescription
typeStringMust be "data.ref".
fromStringTarget path. Must be "/metadata/scope". It can be omitted as it defaults to this value.
selectObjectSelection expression to specify the variable to reference.
select.byObjectSelection method. Must be "name".
select.valueObjectVariable 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:

PositionFieldAllowed ValuesSpecial Characters
1Second0-59* /
2Minute0-59* /
3Hour0-23* /
4Day of month1-31, * ?
5Month1-12, - *
6Day of week
  • 1:Monday
  • 2:Tuesday
  • 3:Wednesday
  • 4:Thursday
  • 5:Friday
  • 6 :Saturday
  • 7:Sunday
, * ?
7YearFour digits, *

Special Characters

Special CharacterMeaningExample Explanation
*All valuesUsing * in the minute field means "every minute"
?No specific valueWhen 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.
-RangeHour field 10-12 means “10, 11 and 12 o’clock”
,Additional valuesWeekday 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 ExpressionMeaning
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 ? 2026Fire 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:
    FormatExampleDescription
    HH:mm13:0013:00 (1:00 PM)
    HH:mm:ss13:00:0113:00:01 (1:00:01 PM, seconds are optional)
    H:mm8:308:30 (8:30 AM)
  • AM/PM format:
    FormatExampleDescription
    h:mm am/pm0:30 am12:30 AM (midnight thirty)
    h:mm am/pm7:30 pm7:30 PM (evening)
    h:mm:ss am/pm8:00:00 am8: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.

FormatExampleDescription
sunrisesunriseThe time when the Sun rises
sunsetsunsetThe time when the Sun sets
sunrise+Durationsunrise+30min30 minutes after sunrise
sunrise-Durationsunrise-1hour1 hour before sunrise
sunset+Durationsunset+30min30 minutes after sunset
sunset-Durationsunset-1hour1 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 satisfied
  • property.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 UnitKeywordExample
Hourhour1hour
Minutemin30min
Secondsec20sec

You can combine multiple units above in the order of hour, min, sec, as shown below:

ExampleDescription
1hour10min20sec1 hour 10 minutes 20 seconds
1hour30min1 hour 30 minutes
10min30sec10 minutes 30 seconds

Complete Examples

Here are three examples of JSON automation scripts:

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
}
]
}
]
}