跳到主要内容

JavaScript 脚本(适用于 HTTP)

本文件介绍了如何通过 JavaScript 脚本在 Aqara Studio 中自定义添加 HTTP 设备和功能点及其解析函数。

脚本介绍

脚本通常涉及以下 9 个函数,请按设备能力实现。静态设备或静态点位场景下,对应 build*Request 函数可以返回 null 或空对象。

函数说明
buildDiscoveryRequest用于生成发现设备的请求报文
parseDiscoveryResponse用于解析发现设备的响应报文
buildDiscoverPointsRequest用于生成查询设备点信息的请求报文
parseDiscoverPointsResponse用于解析设备点信息的响应报文,返回点的详细信息
buildReadRequest用于生成读取设备点数据的请求报文
parseReadResponse用于解析读取点数据的响应报文,返回点的值
buildWriteRequest用于生成写入设备点数据的请求报文
parseWriteResponse用于解析写入点数据的响应报文,返回是否成功
parseReportRequest用于解析设备上报的报文,提取设备ID、点ID、点值等信息
提示

请勿更改函数的名称和参数。

脚本全局变量

协议脚本可以使用 globalThis.studioScriptState 在同一个 Context 的多次函数调用之间共享少量临时状态。该变量默认初始化为空对象:

globalThis.studioScriptState = {
requestCount: 0,
lastValue: null
};

请保持该变量为普通对象。对象属性可保存字符串、有限数值、布尔值、null、普通对象和数组,并可使用这些类型相互嵌套。日期应先转换为字符串。不要保存 undefined、函数、SymbolBigIntNaNInfinity、循环引用、MapSet、Java/Host 对象或自定义类实例;这些值可能被忽略、转换失真或导致序列化失败。

状态大小按序列化后的 UTF-8 JSON 字节数计算,告警阈值为 2 MiB。Studio 在脚本调用后限频检查,首次越界时会同时向服务日志和协议配置页的 Console Content 写入一条 [warn];持续超限不会定期重复打印,也不会自动删除状态或终止本次调用。开发脚本时应确保该变量长期保持在 2 MiB 以内。

Context 被空闲回收、内存压力回收、脚本更新或执行超时后,globalThis.studioScriptState 会重新初始化。请勿用它保存必须持久化的设备状态、凭据或无限增长的历史消息。

前提条件

在编写脚本前,请先详细了解目标设备的以下 HTTP 接口信息,包括但不限于:请求地址、请求方法、请求头、请求参数及响应数据结构等。建议重点关注以下接口:

  • 设备发现接口
  • 功能点(属性点)查询接口
  • 功能点数据读取接口
  • 功能点数据写入接口
  • 功能点数据上报接口

只有充分理解上述接口,才能确保 JavaScript 脚本按照设备规范正确对接 HTTP 协议并完成数据解析。

buildDiscoveryRequest

请在该函数中返回一个请求配置对象,用于指示 Aqara Studio 如何通过 HTTP API 发现设备。

入参说明

建议本函数无任何参数。

返回值

为确保 Aqara Studio 可以正常向设备发起请求,您需要确保 buildDiscoveryRequest 函数返回的数据的格式与下列一致:

{
"path": "/report/discoveryDevices",
"method": "POST",
"headers": "{\"Content-Type\":\"application/json\"}",
"postParams": "{\"appId\":\"V0001\"}"
}

字段说明如下:

字段类型含义
pathString请求路径。用于指定设备发现接口地址,例如 /report/discoveryDevices
如果 methodGET 且包含参数,可直接拼接到 path,例如 /discoveryDevices?channel=1
methodStringHTTP 请求方法,支持 GETPOST,用于指定调用发现接口时使用的 HTTP 请求方式。
headersString请求头,JSON 字符串格式(例如:{"Content-Type":"application/json"}
postParamsStringPOST 请求体参数,JSON 字符串格式(例如:{"appId":"V0001"})。
提示

请根据设备官方技术文档或联系设备技术支持获取 pathmethodheaderspostParams

函数示例

function buildDiscoveryRequest() {
return {
path: "/report/discoveryDevices",
method: "POST",
headers: JSON.stringify({
"Content-Type": "application/json"
}),
postParams: JSON.stringify({
"appId": "V0001"
})
};
}

parseDiscoveryResponse

请在此函数中解析设备发现请求结果,并返回包含设备 ID(deviceId)和设备名称(deviceName)的设备列表对象数组,供 Aqara Studio 使用。

入参说明

建议该函数只接收一个 string 参数用于传入设备发现请求的返回结果。

返回值

为确保 Aqara Studio 可以正常获取设备信息,您需要确保 parseDiscoveryResponse 函数返回的数据的格式与下列一致:

[
{
"deviceId": "123456",
"deviceName": "温度传感器"
}
]

函数示例

假设设备发现接口返回的数据如下:

{
"reply": {
"data": {
"meta": {
"limit": 10,
"offset": 0
},
"list": [
{
"deviceId": "123456",
"deviceName": "test1",
"ip": "127.0.0.1",
"createTime": "qwerasd"
}
]
},
"returnCode": {
"type": "S",
"code": "AAAAA",
"domain": null
}
}
}

如需处理上述数据,您可参考以下示例设计此函数:

function parseDiscoveryResponse(responseString) {
if (!responseString) return [];
let obj;
try {
obj = JSON.parse(responseString);
} catch (e) {
return [];
}
const list = obj?.reply?.data?.list;
if (!Array.isArray(list)) return [];
// 返回数组,每个元素包含 deviceId 和 deviceName
return list.map(item => ({
deviceId: item.deviceId,
deviceName: item.deviceName
}));
}

buildDiscoverPointsRequest

请在该函数中返回一个请求配置对象,用于指示 Aqara Studio 如何通过 HTTP API 查询指定设备的功能点(points)。如果返回 null、空对象或没有 path 字段,平台不会发送 HTTP 请求,会直接调用 parseDiscoverPointsResponse()

入参说明

建议该函数只接收一个 string 参数,用于传入目标设备 ID。

返回值

为确保 Aqara Studio 可以正常向设备发起请求,您需要确保 buildDiscoveryRequest 函数返回的数据的格式与下列一致:

{
"path": "/device/points?deviceId=123456",
"method": "GET",
"headers": "{\"Content-Type\":\"application/json\"}",
"postParams": "{\"deviceId\":\"123456\"}"
}

字段说明如下:

字段类型含义
pathString请求路径。用于指定查询设备功能点的接口地址,
如果 methodGET 且包含参数,可直接拼接到 path,例如 /device/points?deviceId=xxx
methodStringHTTP 请求方法,支持 GETPOST,用于指定调用发现接口时使用的 HTTP 请求方式。
headersString请求头,JSON 字符串格式(例如:{"Content-Type":"application/json"}
postParamsStringPOST 请求体参数,JSON 字符串格式(例如:{"deviceId":"123456"})。
提示

请根据设备官方技术文档或联系设备技术支持获取 pathmethodheaderspostParams

函数示例

function buildDiscoverPointsRequest(deviceId) {
return {
path: `/device/points?deviceId=${deviceId}`,
method: "GET",
headers: JSON.stringify({
"Content-Type": "application/json"
}),
postParams: ""
};
}

parseDiscoverPointsResponse

请在此函数中解析功能点发现请求结果,并返回包含所有功能点信息的数组。

Aqara Studio 会自动调用此函数,您需要在返回的数组中按要求填写每个功能点的详细结构(例如 pointId、pointName 等,具体请参见point 对象结构)。

通过正确实现本函数,Aqara Studio 才能识别和接入设备支持的全部功能点,从而实现功能点的自动发现与控制。

入参说明

建议该函数只接收一个 string 参数,用于传入功能点发现请求结果。

返回值

为确保 Aqara Studio 可以正常获取功能点信息,您需要确保 parseDiscoverPointsResponse 函数返回的数据为 point 对象结构 数组。

point 对象结构

字段名称是否必填说明
pointId必填功能点 ID。请咨询设备厂商获取功能点的真实 ID,以便 Aqara Studio 发现该点。
pointName必填您自定义的功能点名称。
devType条件必填对应 Aqara 物模型规范的 deviceType。基于 Aqara Spec 定义功能点时填写,具体可用值请阅读 设备类型
functionCode条件必填对应 Aqara 物模型规范的 functionCode。基于 Aqara Spec 定义功能点时填写,具体可用值请阅读 功能代码
traitCode条件必填对应 Aqara 物模型规范的 traitCode。基于 Aqara Spec 定义功能点时填写,具体可用值请阅读 功能点代码
dataType条件必填通用功能点必填。功能点数据类型,支持以下取值:
  • bool / boolean:布尔型
  • numerical / number:数值型
  • enum:枚举型
  • text / string:文本型
enumRange条件必填枚举选项数组。仅当通用功能点的 dataTypeenum 时必填。数组不能为空;每项包含整数类型的 value 和字符串类型的 labelvaluelabel 均不可重复,且 label 不可为空。
trueText / falseText可选布尔型通用功能点的显示文案。仅当 dataTypebool / boolean 时生效;未配置时默认 trueTextfalseText。仅在需要自定义文案时配置,例如 启用 / 禁用。也可使用 activeText / onTextinactiveText / offText 作为别名。
min可选数值型通用功能点的最小值。仅当 dataTypenumerical / number 时生效;也可使用 minimum 作为别名。
max可选数值型通用功能点的最大值。仅当 dataTypenumerical / number 时生效;也可使用 maximum 作为别名。
step可选数值型通用功能点的步长,必须大于 0。仅当 dataTypenumerical / number 时生效;也可使用 resolution 作为别名。
precision可选数值型通用功能点的精度值,必须大于等于 0。仅当 dataTypenumerical / number 时生效。
decimals可选数值型通用功能点的小数位数,必须为大于等于 0 的整数。仅当 dataTypenumerical / number 时生效。
unit / units可选数值型通用功能点的单位。仅当 dataTypenumerical / number 时生效;建议填写系统已注册的单位名称,例如 kilowatt hourwattvoltamperecelsiuspercent。Studio 会展示对应符号,例如 kWhWVA°C%。完整映射请参见 脚本支持的单位名称与符号。系统也可匹配已注册的单位符号。
access条件必填通用功能点必填。读写类型,
  • 1:仅可读
  • 2:可读可写
备注

对于 numerical / number 点,Aqara Studio 在写值调用 buildWriteRequest 时会优先依据 decimals 格式化数值;未配置 decimals 时会依据 step / resolution 推导小数位。为了避免 0.3 被二进制浮点误差表现为 0.30000030249357224,建议需要小数写入的点显式配置 decimalsstepprecision 仅用于描述精度,不作为写值报文的小数位截断规则。

如果数值点会被能耗统计或其他依赖单位的功能使用,请配置 unitunits,例如累计电量使用 kilowatt hour(显示 kWh),当前功率使用 watt(显示 W),电压使用 volt(显示 V),电流使用 ampere(显示 A),温度使用 celsius(显示 °C)。单位名称请按 脚本支持的单位名称与符号 中的原文填写,大小写和空格保持一致。

提示

您可以根据实际情况选择以下任意方式构造功能点的数据结构:

  • 基于 Aqara Spec:需填写 devTypefunctionCodetraitCode 等字段,这可以将设备的功能点关联到 Aqara Spec 协议中的对应功能点。
  • 通用方式:需填写 dataTypeaccess 等基本字段。

示例

为确保 Aqara Studio 可以正常获取设备信息,您需要确保 parseDiscoverPointsResponse 函数返回的数据的格式与下列一致:

  • 基于 Aqara Spec:

    [
    {
    "pointId": "temperature",
    "pointName": "温度",
    "devType": "TemperatureSensor",
    "functionCode": "Temperature",
    "traitCode": "CurrentTemperature"
    }
    ]
  • 使用通用方式:

    [
    {
    "pointId": "temperature",
    "pointName": "温度",
    "dataType": "numerical",
    "min": -20,
    "max": 50,
    "step": 0.1,
    "precision": 0.1,
    "decimals": 1,
    "unit": "celsius",
    "access": "1"
    },
    {
    "pointId": "mode",
    "pointName": "运行模式",
    "dataType": "enum",
    "enumRange": [
    { "value": 0, "label": "关闭" },
    { "value": 1, "label": "自动" }
    ],
    "access": "2"
    }
    ]

函数示例

function parseDiscoverPointsResponse(responseString) {
if (!responseString) return [];
let obj;
try {
obj = JSON.parse(responseString);
} catch (e) {
return [];
}
const list = obj?.reply?.data?.points;
if (!Array.isArray(list)) return [];
return list.map(item => ({
pointId: item.pointId,
pointName: item.pointName,
devType: item.devType,
functionCode: item.functionCode,
traitCode: item.traitCode
}));
}

buildReadRequest

当 Aqara Studio 需要获取设备的状态数据(例如开关状态、温度、模式等)时,会调用此函数,传入目标设备 ID(deviceId)以及需要读取的单个功能点 ID(pointId)。

请在该函数中返回一个请求配置对象,用于指示 Aqara Studio 如何通过 HTTP API 查询指定设备的功能点(points)的值。

入参说明

建议该函数接收两个 string 参数,用于传入设备 ID 和功能点 ID。

返回值

为确保 Aqara Studio 可以正常获取功能点信息,您需要确保 buildReadRequest 函数返回的数据的格式与下列一致:

{
"path": "/device/read/temperature",
"method": "GET",
"headers": "",
"postParams": ""
}
提示

当前代码按单点读取调用该函数,第二个参数是 pointId,返回值是单个请求对象。

字段说明如下:

字段类型含义
pathString请求路径。用于指定查询设备功能点的接口地址。
如果 methodGET 且包含参数,可直接拼接到 path。
methodStringHTTP 请求方法,支持 GETPOST,用于指定调用发现接口时使用的 HTTP 请求方式。
headersString请求头,JSON 字符串格式(例如:{"Content-Type":"application/json"}
postParamsStringPOST 请求体参数,JSON 字符串格式(例如:{"deviceId":"123456"})。
提示

请根据设备官方技术文档或联系设备技术支持获取 pathmethodheaderspostParams

函数示例

function buildReadRequest(deviceId, pointId) {
if (!deviceId || !pointId) return {};
return {
path: `/device/read/${deviceId}/${pointId}`,
method: "GET",
headers: "",
postParams: ""
};
}

parseReadResponse

本接口用于解析功能点读取请求结果(原始数据)。

请在本函数中将设备返回的原始数据转换为 Aqara Studio 可以识别的功能点数据格式。

入参说明

建议该函数接收两个 string 参数,用于传入设备 ID 和 HTTP 响应字符串。

返回值

为了确保 Aqara Studio 能正确获取功能点的数据,您需要保证 parseReadResponse 函数返回的数据格式与下方示例一致:

{
"temperature": "22.5",
"humidity": "60"
}

字段说明:每个 key 表示功能点,对应的 value 为该点的值(均为字符串类型)。

函数示例

function parseReadResponse(deviceId, responseString) {
if (!responseString) return {};
let obj;
try {
obj = JSON.parse(responseString);
} catch (e) {
return {};
}
const result = {};
if (obj.data && Array.isArray(obj.data)) {
obj.data.forEach(item => {
for (const key in item) {
if (Object.prototype.hasOwnProperty.call(item, key)) {
result[key] = String(item[key]);
}
}
});
}
return result;
}

buildWriteRequest

当您向在 Aqara Studio 上控制设备的功能点(如开关、温度、模式等)时,Aqara Studio 会调用此函数,并传入目标设备 ID(deviceId)、要控制的功能点 ID(pointId)以及要设置的目标值(value)。

请在该函数中返回一个请求配置对象,指示 Aqara Studio 应如何通过 HTTP API 向设备下发控制指令。

入参说明

建议该函数接收三个 string 参数,用于传入设备 ID 和功能点 ID 和功能点值。

返回值

为确保 Aqara Studio 可以正常控制功能点,您需要确保 buildWriteRequest 函数返回的数据的格式与下列一致:

{
path: "/device/write/temperature",
method: "POST",
headers: "",
postParams: "{\"value\":22.5}"
}

字段说明如下:

字段类型含义
pathString请求路径。用于指定写入设备点的接口地址。
如果 methodGET 且包含参数,可直接拼接到 path,例
methodStringHTTP 请求方法,支持 GETPOST,用于指定调用发现接口时使用的 HTTP 请求方式。
headersString请求头,JSON 字符串格式(例如:{"Content-Type":"application/json"}
postParamsStringPOST 请求体参数,JSON 字符串格式(例如:{"value":22.5})。
提示

请根据设备官方技术文档或联系设备技术支持获取 pathmethodheaderspostParams

函数示例

function buildWriteRequest(deviceId, pointId, value) {
if (!deviceId || !pointId) return {};
return {
path: `/device/write/${deviceId}/${pointId}`,
method: "POST",
headers: JSON.stringify({
"Content-Type": "application/json"
}),
postParams: JSON.stringify({ value: value })
};
}

parseWriteResponse

本接口用于解析功能点写入(控制)接口请求结果,用于判断设备的控制指令是否执行成功。

当 Aqara Studio 向设备发起写入请求(例如开关设备、调节温度等)并接收到设备返回结果时,会调用此函数,根据返回值,判断控制是否成功。

请在本函数中解析设备返回的数据,并将其转换为布尔值,便于 Aqara Studio 判断控制指令是否执行成功。

入参说明

建议该函数接收两个 string 参数,用于传入设备 ID 和功能点写入(控制)接口请求结果。

返回值

请确保函数返回值为布尔值,布尔值说明如下:

  • true:功能点写入成功
  • false:功能点写入失败或设备返回异常

函数示例

function parseWriteResponse(pointId, responseString) {
if (!responseString) return false;
let obj;
try {
obj = JSON.parse(responseString);
} catch (e) {
return false;
}
return obj.result === "success";
}

parseReportRequest

当设备主动向 Aqara Studio 上报数据时(例如设备状态变化、传感器上报数据等),Aqara Studio 会调用此函数,从设备主动上报的数据中提取设备 ID 和各个功能点的上报数据,用于更新设备状态。每个 HTTP 上报请求只调用一次该函数,并通过 points 数组一次返回请求中的所有功能点值。

请在本函数中将设备返回的原始数据转换为 Aqara Studio 可以识别的功能点数据格式。

前提条件

请确保设备端严格按照以下 Endpoint、方法及请求体要求向 Aqara Studio 进行数据上报:

  • Endpoint:http://{ip}:8000/report/data
  • 请求方法:POST
  • 请求体:由您自定义,只需确保能通过 parseReportRequest 接口解析获得下述返回值规定的设备信息字段,即 deviceIdpoints

入参说明

建议该函数接收两个 string 参数:

  • 第一个参数:传入 Aqara Studio 用于接收设备数据的 Endpoint,即上述 http://{ip}:8000/report/data
  • 第二个参数:设备数据上报请求体。

请保证参数命名和顺序正确,以便 Aqara Studio 能准确识别并处理指定路径下的设备上报数据。

返回值

返回值应包含以下三个字段:

字段类型说明
deviceIdString设备 ID,用于标识当前数据所属的设备。
pointsList<Map<String, String>>点信息列表,表示设备的多个点数据。每个点为一个 Map,包含:
  • pointId:功能点 ID
  • value:点值
responseMsgString响应消息,用于告知设备端 Aqara Studio 是否成功接收该数据。

为了确保 Aqara Studio 能正确获取功能点的数据,您需要保证 parseReportRequest 函数返回的数据格式与下方示例一致:

{
deviceId: "123456",
points: [
{
pointId: "temperature",
value: "22.5"
}
],
responseMsg: ""
}

函数示例

function parseReportRequest(path, requestString) {
if (!requestString) return { deviceId: "", points: [], responseMsg: "" };
let obj;
try {
obj = JSON.parse(requestString);
} catch (e) {
return { deviceId: "", points: [], responseMsg: "" };
}
const deviceId = obj.deviceld || obj.deviceId || "";
const points = [];
const parans = obj.data && obj.data.parans ? obj.data.parans : {};
for (const pointId in parans) {
if (Object.prototype.hasOwnProperty.call(parans, pointId)) {
const item = parans[pointId];
points.push({
pointId: pointId,
value: String(item.value)
});
}
}
return { deviceId: deviceId, points: points, responseMsg: "" };
}

完整示例

以下代码涵盖上述 9 个函数的示例。请根据实际设备的接口和数据格式进行相应调整与优化,勿直接完全照搬。

示例中的 globalThis 注册是动态的:脚本实际实现了哪些函数,就只注册哪些函数;未实现的函数不需要注册。

(function(){

// 仅保存可 JSON 序列化的临时状态;Context 重建后会清空。
const scriptState = globalThis.studioScriptState;
scriptState.reportCount = 0;
scriptState.lastReportAt = null;

function buildDiscoveryRequest() {
return {
path: "/report/discoveryDevices",
method: "POST",
headers: JSON.stringify({
"Content-Type": "application/json"
}),
postParams: JSON.stringify({
"appId": "V0001"
})
};
}

function parseDiscoveryResponse(responseString) {
if (!responseString) return [];
let obj;
try {
obj = JSON.parse(responseString);
} catch (e) {
return [];
}
const list = obj?.reply?.data?.list;
if (!Array.isArray(list)) return [];
// 返回数组,每个元素包含 deviceId 和 deviceName
return list.map(item => ({
deviceId: item.deviceId,
deviceName: item.deviceName
}));
}

function buildDiscoverPointsRequest(deviceId) {
return {
path: `/device/points?deviceId=${deviceId}`,
method: "GET",
headers: JSON.stringify({
"Content-Type": "application/json"
}),
postParams: ""
};
}

function parseDiscoverPointsResponse(responseString) {
if (!responseString) return [];
let obj;
try {
obj = JSON.parse(responseString);
} catch (e) {
return [];
}
const list = obj?.reply?.data?.points;
if (!Array.isArray(list)) return [];
return list.map(item => ({
pointId: item.pointId,
pointName: item.pointName,
devType: item.devType,
functionCode: item.functionCode,
traitCode: item.traitCode
}));
}

function buildReadRequest(deviceId, pointId) {
if (!deviceId || !pointId) return {};
return {
path: `/device/read/${deviceId}/${pointId}`,
method: "GET",
headers: "",
postParams: ""
};
}

function parseReadResponse(deviceId, responseString) {
if (!responseString) return {};
let obj;
try {
obj = JSON.parse(responseString);
} catch (e) {
return {};
}
const result = {};
if (obj.data && Array.isArray(obj.data)) {
obj.data.forEach(item => {
for (const key in item) {
if (Object.prototype.hasOwnProperty.call(item, key)) {
result[key] = String(item[key]);
}
}
});
}
return result;
}

function buildWriteRequest(deviceId, pointId, value) {
if (!deviceId || !pointId) return {};
return {
path: `/device/write/${deviceId}/${pointId}`,
method: "POST",
headers: JSON.stringify({
"Content-Type": "application/json"
}),
postParams: JSON.stringify({ value: value })
};
}

function parseWriteResponse(pointId, responseString) {
if (!responseString) return false;
let obj;
try {
obj = JSON.parse(responseString);
} catch (e) {
return false;
}
return obj.result === "success";
}

function parseReportRequest(path, requestString) {
scriptState.reportCount += 1;
scriptState.lastReportAt = new Date().toISOString();
if (!requestString) return { deviceId: "", points: [], responseMsg: "" };
let obj;
try {
obj = JSON.parse(requestString);
} catch (e) {
return { deviceId: "", points: [], responseMsg: "" };
}
const deviceId = obj.deviceld || obj.deviceId || "";
const points = [];
const parans = obj.data && obj.data.parans ? obj.data.parans : {};
for (const pointId in parans) {
if (Object.prototype.hasOwnProperty.call(parans, pointId)) {
const item = parans[pointId];
points.push({
pointId: pointId,
value: String(item.value)
});
}
}
return { deviceId: deviceId, points: points, responseMsg: "" };
}

globalThis.buildDiscoveryRequest = buildDiscoveryRequest;
globalThis.parseDiscoveryResponse = parseDiscoveryResponse;
globalThis.buildDiscoverPointsRequest = buildDiscoverPointsRequest;
globalThis.parseDiscoverPointsResponse = parseDiscoverPointsResponse;
globalThis.buildReadRequest = buildReadRequest;
globalThis.parseReadResponse = parseReadResponse;
globalThis.buildWriteRequest = buildWriteRequest;
globalThis.parseWriteResponse = parseWriteResponse;
globalThis.parseReportRequest = parseReportRequest;

})()

排查脚本问题

在完成脚本开发后,如果您无法在 Aqara Studio 完成发现设备或功能点等操作,请参考以下步骤检查脚本是否正常运行:

  1. 使用 控制台日志 检查脚本内各方法是否被正常调用;
  2. 阅读 脚本检查要点,逐项检查脚本是否满足 Aqara Studio 的校验要求。
  3. 如果以上步骤都无法解决问题,可能是因为 Aqara Studio 的 运行资源限制 导致脚本无法正确运行。

控制台日志

  1. 为调试和排查脚本各方法(例如 parseDiscoveryResponseparseDiscoverPointsResponse 等),可在函数内部任意位置添加如下控制台日志方法:

    • console.log
    • console.info
    • console.debug
    • console.warn
    • console.error
    提示

    请勿在循环或高频报文处理函数中无条件输出日志,调试时应使用条件开关或采样输出。

    示例代码:

    function parseDiscoveryResponse() {
    console.info("开始解析发现响应", arguments);
    return [
    {
    deviceName: "xxx",
    // ...
    }
    ];
    }
    添加控制台日志示例
    提示
    • 多参数时,日志内容将使用空格拼接输出。
    • console.warnconsole.error 的输出分别带有 [warn][error] 前缀。
  2. 在 Aqara Studio 中重新发起相关操作(如设备发现、功能点发现、功能点读取、写入、上报等),即可触发包含日志的方法。

  3. 进入 HTTP 协议配置 页面,查看 Console Content 字段是否有日志输出:

    • 若日志正常显示,说明方法已正确接入;
    • 若没有日志,请检查方法实现是否有误。
    提示
    • Console Content 最多保留 2048 个字符;超出限制时旧内容会被替换。
    • 每个脚本解析器每秒最多接收 20 条日志,超出部分会被忽略并在下一时间窗口输出汇总提示。单条日志最多保留 512 个字符并转换前 16 个参数。

脚本检查要点

建议您结合 Aqara Studio 各业务节点的校验流程,逐项检查脚本是否满足平台要求,确保各关键节点通过校验,提升脚本可靠性与兼容性。

业务节点调用函数主要校验
脚本加载完整脚本脚本不超过 1,048,576 个字符,并且能够被 JavaScript 引擎执行;业务函数在实际调用时还会检查是否存在且可执行。
设备发现buildDiscoveryRequest() / parseDiscoveryResponse(response)请求函数可省略或返回空值;非空结果必须可转换为 HTTP 请求配置。发现结果必须是数组,单次最多处理 128 个设备,并逐项校验设备信息。
功能点发现buildDiscoverPointsRequest(deviceId) / parseDiscoverPointsResponse(deviceId, response)响应按 UTF-8 计算不得超过 256 KiB;发现结果必须是数组,单次最多处理 512 个功能点,并逐项校验功能点结构。
功能点读取和写入buildReadRequest / parseReadResponse / buildWriteRequest / parseWriteResponse请求结果必须可转换为 HTTP 请求配置;响应不得超过 256 KiB;解析结果必须包含可识别的功能点和值。
设备主动上报parseReportRequest(path, requestString)请求体按 UTF-8 计算不得超过 256 KiB;返回值必须包含 deviceIdpoints 数组,单次最多处理 512 项,并逐项校验 pointIdvalue

运行资源限制

  • 传入 JavaScript 的单个 HTTP 响应或上报请求体按 UTF-8 计算不得超过 256 KiB;超过限制的数据不会交给 JavaScript 处理,上报请求会返回 HTTP 413
  • 单次设备发现最多处理 128 个设备,单次功能点发现最多处理 512 个功能点;超出部分会被忽略。
  • 单个 HTTP 主动上报请求最多处理 512 个功能点值;超出部分会被忽略。
  • 脚本 Context 在长时间无调用或系统内存压力较高时可能被回收并在下次调用时重建。请勿依赖全局变量永久保存设备状态,持久状态应保存在设备或 Studio 功能点中。
  • 当脚本执行队列已满或系统内存压力较高时,本次脚本调用可能被拒绝。设备主动上报应具备合理的重试或后续状态补报机制。