# 技术方案

# 注:大卡片、小组件、灵动岛脚本代码需维护在同一份文件上,根据不同字段内容区分

# 首页卡片展示方案(大小卡片展示逻辑)

  • 实现逻辑:3.1.0版本开始,首页接口返回(品类+sn8)配置有脚本,并且首页接口配置的是3.1.0及以上版本的脚本,就支持显示大卡片+定制化小卡片,否则,默认小卡片实现;

# 首页大片刷新按钮展示逻辑

  • 原生实现逻辑:当lua查询失败时,或脚本返回unknowStatus:true时,需要展示刷新按钮,脚本对接人需要和产品同步那种B5功能缺失时,返回unknowStatus:true

# 原生脚本交互接口

  • 原生入参示例:
{
    "deviceSn": "000000P0000000Q1A0681CAE921C0000",
    "deviceId": "24189255812085",
    "deviceStatus": {},
    "isOnline": "0/1"
}
// deviceId:设备id,
// deviceStatus:设备状态
// isOnline:设备在线离线状态,String类型,0:离线;1:在线

# 脚本输出结果

  • 脚本输出结构示例:
{
    "extras": {
        "queryType": [{
            "value": "xxx,xxx"
        }, {
            "value": "xxx,xxx"
        }]
    },
    "unknown_status": true,
    "baseInfo": {},
    "powerModule": {},
    "animationModule": {},
    "mainFunModule": {},
    "minorFunModule": [],
    "workStatusModule": [],
    "thermostatModule": {},
    "stateIslandModule": {}
}

# 指定lua参数查询

"extras": {
    // lua查询指令值,按数组顺序下发;value值对应查询指令,不做额外处理
    // 首次解析大卡片脚本后才会根据该字段进行二次查询
    "queryType": [{
        "value": "xxx,xxx"
    }, {
        "value": "xxx,xxx"
    }]
}

# 设备状态未知

"unknown_status": true, // Bool类型,设备状态未知  

状态说明:

  • 未获取到设备状态(lua查询失败):原生处理
  • 离线状态:脚本处理,入参jsonData增加isOnline:"0/1"
  • 设备故障:脚本处理(针对不同功能按钮分别判断)
    !!卡片上任意显示状态未知,整体置为状态未知,提供刷新按钮

# 基础信息(示例图中环境信息):baseInfo

"baseInfo": {
	"displayEnvironment": true, //BOOL类型 是否显示环境信息内容
	"displayDeviceStatus": true, //BOOL类型 是否显示设备信息内容
	"environment": [ // type字段解析:language:多语言词条,若无匹配多语言数据,则直接显示词条;value:文案,直接显示;unit:单位,直接显示
		{
			"type": "language", // 环境信息名词
			"value": "language_key",
		},
		{
			"type": "value", // 环境信息值
			"value": "30",
		},
		{
			"type": "unit", // 环境信息单位
			"value": "°C",
		},
	], // Array类型,展示的环境信息,根据类型type,进行数据拼接,拼接顺序根据当前语种(阿拉伯语和希伯来语语序问题)
	"deviceStatus": "", // String类型,设备当前状态,返回多语言文案key,支持单一状态显示
	"warningStatus": true, // Boolean类型,控制设备状态文案是否展示错误提示色
	"envirWarningStatus": false, // Boolean类型,控制环境信息文案是否展示错误提示色,缺少该字段,默认正常字体颜色-2024.7.10新增
	// 同时显示环境信息和设备信息时,中间会以竖线分割;当前后两个内容都显示为错误提示色时,竖线也显示错误提示色
}

# 设备启停:powerModule

"powerModule": {
    "display": true, //BOOL类型 是否显示;离线状态下,开关机按钮必须隐藏
    "power": 0, // Int类型,当前启停状态;0:关机;1:开机
    "enable": true, //BOOL类型,样式是否置灰,和是否响应交互无关
    "clickEvent": {
        // clickEvent.clickable = flase    点击完全不响应
        // clickEvent.clickable = true && toastkey有值    仅toast提示
        // clickEvent.clickable = true  && toastkey值为空字符串    可控制或进入二级页面
        "clickable": false, // 置灰时是否可点击
        "toastLanguageKey": "", // 点击按钮后不执行动作,toast提示内容,clickable为true且toastLanguageKey不为空,则toast提示。
        "showDialog": false, // BOOL类型 是否弹窗,优先级高于toast
        "dialogConfig": {
            "content": "", // 弹窗内容,多语言key
            "contentReplace": "", // 弹窗内容替换值,传空字符串为不替换
            "firstBtn": "", // 第一按钮文案,多语言key,点击confirm按钮后执行control控制代码,不涉及控制则不传按钮文案,为空字符串不显示该按钮
            "secondBtn": "", // 第二按钮文案,多语言key,点击关闭dialog
        }
    },
    "control": { "coverCode": "$powerModuleControl$" }, //控制代码,由脚本生成压入
    "stateIslandIcon": { // 状态岛设备运行中icon,图片资源由国际智能提供,必传参数
        "isApng": true, // 是否apng图片,true:apng图片;false:普通图片
        "iconFromHttp": true, // 图片地址是否网络OSS资源,true:网络OSS资源;false:本地资源
        "icon": "", // 在线apng图片OSS地址,待确认OSS地址国外访问是否正常
    }
}

# 设备图片动画:animationModule

"animationModule": {
    "displayStaticImage": true,           // 是否显示从idcp获取的设备型号图
    "displayAnimationBackground": false,  // 是否显示动图,动图显示在设备型号图底层
    "animationBackground": "",            // 背景动图路径,String类型,图片名称,考虑到带动画效果的apng图片不能被压缩,暂时仅支持本地资源图片
    "isApng": true,                       // 区分animationBackground是apng还是png,两种格式图片原生渲染方式不一样,默认按apng格式加载
    "overImage": {                        // 覆盖在设备型号图上的图片信息-国际美居V3.10.0;国际东芝V2.7.0
        "display": false,                 // 是否展示覆盖图
        "overImageUrl": "",               // 图片文件名,
        "imageFromHttp": false,           // icon图片来源,true:网络资源,false:本地资源,原生需拼接完整路径地址,如果是apng图片,不支持网络来源
        "isApng": false,                  // 区分图片是apng/普通png,ture:apng,false:普通
    },
    "centerValue": {                      // 覆盖在上层文案信息,居中显示-国际美居V3.10.0;国际东芝V2.7.0
        "display": true,                  // 是否展示中央数据
        "type": "value",                  // 值类型,value:具体数据;language:以多语言形式展示
        "value": "72",                    // 具体值,传数据/多语言key
    }
}

# 一级功能:mainFunModule

"mainFunModule": {
    "display": true, // BOOL类型 是否显示
    "enable": true, // BOOL类型,样式是否置灰,同时滑杆不支持滑动
    "viewType": 0, // Int类型,枚举见viewType
    "viewTypeConfig": {}, //见下面表格定义
    "clickEvent": {
        "clickable": false, // BOOL类型 是否可点击
        "toastLanguageKey": "", // 点击按钮后不执行动作,toast提示内容
        "showDialog": false, // BOOL类型 是否弹窗,优先级高于toast
        "dialogConfig": {
            "content": "", // 弹窗内容,多语言key
            "contentReplace": "", // 弹窗内容替换值,传空字符串为不替换
            "firstBtn": "", // 第一按钮文案,多语言key,点击confirm按钮后执行control控制代码,不涉及控制则不传按钮文案,为空字符串不显示该按钮
            "secondBtn": "", // 第二按钮文案,多语言key,点击关闭dialog
        }
    },
    "control": { "coverCode": "$mainFunModuleControl$" } // 控制代码,由脚本生成压入
}

# 一级功能支持样式枚举,样式key:viewType

枚举值 配置值 UI样式 说明 setValue控制入参示例
0 详情见下方demo 一级功能UI样式图 slider样式,左边右边各有一个加减按钮 setValue: 26
1 详情见下方demo 一级功能UI样式图 纯文案显示样式,支持多语言key/自定义显示内容 -
  • 注1
// viewType = 0
"viewTypeConfig": {
    "min": 16, // Int类型 最小值
    "max": 30, // Int类型 最大值
    "step": 0.5, // Double类 型步长
    "unit": "", // String类型 单位,不带单位传空字符串
    "currentValue": {
        "type": "language/value",
        "label": "", // 显示内容,type=language时取值式
        "value": "", // 显示内容,type=value时取值
    },
    "floatCount": 1, // Int类型,支持多少位小数。默认0位,
}

// viewType = 1
"viewTypeConfig": { // 若需隐藏文案,但保持布局间隙,可将value置为空字符串
    "type": "value", // 值类型
    "value": "", // 多语言key/显示值
}

# 二级功能:minorFunModule

"minorFunModule": [
    { 
        "displayExtend": true, //是否展开二级页面,e.g. 扫地机false, 空调模式,风速true
        "enable": true, //BOOL类型,样式置灰
        "clickEvent": {
            "clickable": false, // 是否可点击
            "toastLanguageKey": "", // 点击按钮后不执行动作,toast提示内容
            "showDialog": false, // BOOL类型 是否弹窗,优先级高于toast
            "dialogConfig": {
                "content": "", // 弹窗内容,多语言key
                "contentReplace": "", // 弹窗内容替换值,传空字符串为不替换
                "firstBtn": "", // 第一按钮文案,多语言key,点击confirm按钮后执行control控制代码,不涉及控制则不传按钮文案,为空字符串不显示该按钮
                "secondBtn": "", // 第二按钮文案,多语言key,点击关闭dialog
            }
        },
        "control": {
            "coverCode": "minorFunModuleLeftSpecialControl" //控制代码,若需要展开二级页面,则需要删除此control,以subModule内为准
        },
        "functionStatus": { // 功能当前状态language_key
            "iconFromHttp": true, // icon资源是否来自网络资源,默认为false,请求本地资源
            "icon": "",
            "type": "language/value",
            "value": "",
            "unit": "",
        },
        "subModule": { // 二级页面相关功能
            "viewType": 0,//Int类型,枚举减viewType
            "viewTypeConfig": {}, //见下面表格定义,
            "functionName": "", // 功能名称language_key,用以大卡片按钮,同时也用于二级页面副标题
            "control":{
                "coverCode": "$minorFunModuleLeftControl$" //控制代码,由脚本生成压入;与上一级control互斥,二选一
            },
            "showSpecialBtn": true, // boolean类型,是否在二级页面展示特殊操作按钮,如空调无级风下的自动风开关
            // 如不存在特殊功能按钮,specialBtnConfig可不定义,但showSpecialBtn必须传false
            "specialBtnConfig": {
                "type": "switch", // 特殊操作按钮样式,目前仅支持switch开关样式
                "label": "", // language_key
                "value": 0, // Int类型,
                "enable": true, //BOOL类型,样式是否置灰
                "clickEvent": {
                    "clickable": false, // 是否可点击
                    "toastLanguageKey": "", // 点击按钮后不执行动作,toast提示内容
                    "showDialog": false, // BOOL类型 是否弹窗,优先级高于toast
                    "dialogConfig": {
                        "content": "", // 弹窗内容,多语言key
                        "contentReplace": "", // 弹窗内容替换值,传空字符串为不替换
                        "firstBtn": "", // 第一按钮文案,多语言key,点击confirm按钮后执行control控制代码,不涉及控制则不传按钮文案,为空字符串不显示该按钮
                        "secondBtn": "", // 第二按钮文案,多语言key,点击关闭dialog
                    }
                },
                "control":{
                    "coverCode": "minorFunModuleLeftSpecialControl" // 控制代码
                }
            },
        }
    }
] 

# 支持1~2个功能按钮,仅有一个功能按钮时,按钮样式拉长;数组为空,代表大卡片不展示二级功能模块,二级功能支持样式枚举,样式key:viewType

枚举值 样式 配置值 UI样式 setValue控制入参示例
0 无级slider 详情见下方demo 二级功能UI样式图
说明:
1. 原生实现小数点保留逻辑,target_value 根据step是否小于1,保留一位小数.
2. 图中的"Fan speed"使用上层的functionName字段
3.预期值Label(上图文案:30%)显示逻辑
动作值:
*用户操作switch按钮从开到关时,预期值Label:max+unit
*用户操作switch按钮从关到开时,预期值label直接显示多语言key为subModule.specialBtnConfig.label
*当switch状态为开启或关闭时,点击slider,预期值Label:value+unit
状态值:
*状态同步时,当switch状态为开启时,预期值label直接显示多语言key为subModule.specialBtnConfig.label
*状态同步时,当switch状态为关闭时,预期值Label:value+unit
setValue: {value: 30}
1 有级Slider 详情见下方demo 二级功能UI样式图
备注:currentValue用于当前状态显示
items的value或label,用于用户交互选中按钮时(未发送命令前)的实时状态的显示
传入items[i]对应的Object
2 Grid样式 详情见下方demo 二级功能UI样式图
备注:currentValue用于当前状态显示
items的value或label,用于用户交互选中按钮时(未发送命令前)的实时状态的显示
传入items[i]对应的Object
// 无级slider数据结构
"viewTypeConfig": {
    "min": 0, // Int类型 最小值
    "max":100, // Int类型 最大值
    "step": 1, // Double类型 步长
    "unit": "", // 单位符号,不存在单位时传空字符串
    "currentValue": {
        "type": "language/value",
        "label": "", // 显示内容,根据type决定解析方式
    },
    "floatCount": 1, // Int类型,支持多少位小数。默认0位,
}
// 有级slider数据结构
"viewTypeConfig": {
    "items": [{
        "type": "language/value",
        "label": "", // 显示内容,根据type决定解析方式
        "controlValue": "", // lua控制值
        "selected": true // 是否选中
    }, {
        "type": "language/value",
        "label": "", // 显示内容,根据type决定解析方式
        "controlValue": "",
        "selected": false
    }],
    "unit": "", // 单位符号,不存在单位时传空字符串
    "currentValue": {
        "type": "language/value",
        "label": "", // 显示内容,根据type决定解析方式
    }
}
// Grid样式数据结构
"viewTypeConfig": {
    "style": 1, // Int类型,1:正方形带圆角,中间icon,底下文案;2:长方形带圆角,中间文案
    "items":[{
        "iconFromHttp": true, // icon资源是否来自网络资源,默认为false,请求本地资源
        "icon": "", // style=1生效,未选中状态下图标
        "iconSelected": "", // 选中状态下图标
        "label": "", // language_key,style=2生效
        "controlValue": "", // lua控制值
        "selected": true // 是否选中
    }],
    "currentValue": {
        "type": "language/value",
        "label": "", // 显示内容,根据type决定解析方式
    }
}

# 工作状态展示模块:workStatusModule

生效版本:国际美居V3.3.0;国际东芝V2.1.0

# 特殊说明:

  • 元素个数代表展示几个展示框,元素下标决定数据跟第几个展示框绑定,允许0~2个,0/不返回该字段需隐藏整个workStatusModule区域。
  • 原生先判断每个元素中needUpdate字段,为true时才取其余字段更新卡片状态;否则取上一次缓存的状态数据。
  • 需要展示两个状态框时,数组必须固定返回两个元素,不涉及更新的数据,可通过needUpdate标识区分。
"workStatusModule": [
    /**
     * 元素个数代表展示几个展示框,元素下标决定数据跟第几个展示框绑定,允许0~2个,0/不返回该字段需隐藏整个workStatusModule区域
     * 原生先判断每个元素中needUpdate字段,为true时才取其余字段更新卡片状态
     * 组合情况:
     * 1、只展示一个信息框
     * 2、展示两个信息框,且两个信息框状态同步返回
     * 3、展示两个信息框,但两个信息框状态不同步返回
     */
    {
        "needUpdate": true, // true:需要原生更新;false:不需要原生更新,原生保留上一次状态数据
        "titleType": "language", // title渲染类型——language:多语言key(原生根据key匹配多语言文案);value:文本文案(直接显示)
        "title": "", // 显示title
        "iconFromHttp": true, // icon资源来源——true:网络资源;false:App本地资源
        "icon": "", // icon链接地址/icon本地资源名称
        "contentType": "", // content渲染类型——language:多语言key(原生根据key匹配多语言文案);value:文本文案(直接显示)
        "content": "", // 显示内容,e.g.空气炸锅剩余工作时间,类型value
        "enable": true, // 样式上是否置灰,true:不置灰;false:置灰
        "isWorking": true // 当前是否处于工作中,workStatusModule返回两个元素时,会取该字段校准baseInfo中的deviceStatus
    }, {
        "needUpdate": false, // true:需要原生更新;false:不需要原生更新,原生保留上一次状态数据
    }
]

# 温控器特殊模块:thermostatModule

生效版本:国际美居V3.10.0;国际东芝V2.7.0

# 特殊说明:

  • controlBtns元素个数代表展示几个控制模块,允许1~2个。
  • 控制入参为:setValue: [Number, Number],入参个数与controlBtns一致
"thermostatModule": { // 温控器module
    "display": true, // BOOL类型 是否显示
    "enable": true, // BOOL类型,样式是否置灰
    "clickEvent": {
        "clickable": true, // BOOL类型 是否可点击
        "toastLanguageKey": "xxx", // 点击按钮后不执行动作,toast提示内容,多语言词条
        "showDialog": false, // BOOL类型 是否弹窗,优先级高于toast
        "dialogConfig": {
            "content": "", // 弹窗内容,多语言key
            "contentReplace": "", // 弹窗内容替换值,传空字符串为不替换
            "firstBtn": "", // 第一按钮文案,多语言key,点击confirm按钮后执行control控制代码,不涉及控制则不传按钮文案,为空字符串不显示该按钮
            "secondBtn": "", // 第二按钮文案,多语言key,点击关闭dialog
        }
    },
    "minDual": 4, // Int类型,双控温最小区间值,非负数
    "controlBtns": [ // 控制按钮数组,元素数量决定控制按钮数量,不超2个
        {
            "min": 16, // Int类型,最小值
            "max": 30, // Int类型,最大值
            "step": 1, // Int类型,步长
            "icon": "", // icon图片文件名
            "iconFromHttp": false, // icon图片来源,true:网络资源,false:本地资源,原生需拼接完整路径地址
            "type": "value", // 值类型,value:具体数据;language:以多语言形式展示
            "value": "", //具体值,传数据/多语言key
            "unit": "", // 单位,有则显示,无则忽略
            "minDual": 4, // Int类型,双控温最小区间值
        }, {
            "min": 16, // Int类型,最小值
            "max": 30, // Int类型,最大值
            "step": 1, // Int类型,步长
            "icon": "", // icon图片文件名
            "iconFromHttp": false, // icon图片来源,true:网络资源,false:本地资源,原生需拼接完整路径地址
            "type": "value", // 值类型,value:具体数据;language:以多语言形式展示
            "value": "", //具体值,传数据/多语言key
            "unit": "", // 单位,有则显示,无则忽略
            "minDual": 4, // Int类型,双控温最小区间值
        }
    ],
    "statusBar": {
        "display": false, // 是否显示statusBar
        "icon": "", // icon图片文件名
        "iconFromHttp": false, // icon图片来源,true:网络资源,false:本地资源,原生需拼接完整路径地址
        "type": "value", // 值类型,value:具体数据;language:以多语言形式展示
        "value": "", //具体值,传数据/多语言key
        "unit": "", // 单位,有则显示,无则忽略
    },
    "control": { "coverCode": "$thermostatModuleControl$"}
}

# 状态岛展示内容模块:stateIslandModule

"stateIslandModule": {
    "environmentInfo": [ // 环境信息,依据设备传感器
        {
            "infoType": 0, // 0:室内温度;1:室内湿度;2:空气质量;新增待定
            "icon": "", // icon图片文件名
            "iconFromHttp": false, // icon图片来源,true:网络资源;false:内置图片
            "desc": "", // String类型,环境信息描述,多语言key,不传则不显示
            "valueType": "value", // value:具体数据;language:以多语言形式展示
            "value": "", // String类型,环境信息值
            "unit": "", // String类型,单位,有则显示,无则忽略
        }, // 一台设备可存在多个环境信息,原生根据infoType分组
    ],
    // 状态岛实际归属【运行中】状态的其中一种场景
    "runningStatus": {
        "isRunning": true, // true/false,是否上岛
        "icon": "", // icon图片文件名,暂定不取型号图,
        "iconFromHttp": false, // icon图片来源,true:网络资源;false:内置图片
        "isApng": true,
        "needMerge": true, // true/false,是否需要合并——无倒计时内容,则告知原生需要合并(同品类)
        "countDownInfos": [
            {
                "needUpdate": true, // true:需要原生更新;false:不需要原生更新,原生保留上一次状态数据——特殊兼容双腔炸锅
                "isWorking": true, // 当前是否处于工作中,countDownInfos返回两个元素时,会取该字段校准runningStatus中的isRunning
                "type": "value", // language:多语言key,原生需转多语言;value:文案,直接显示
                "value": "00:25", // 多语言key或直接显示的内容
            }, {
                "needUpdate": false, // true:需要原生更新;false:不需要原生更新,原生保留上一次状态数据——特殊兼容双腔炸锅
                "isWorking": true, // 当前是否处于工作中,countDownInfos返回两个元素时,会取该字段校准runningStatus中的isRunning
                "type": "value", // language:多语言key,原生需转多语言;value:文案,直接显示
                "value": "", // 多语言key或直接显示的内容
            } // 中间斜杠有原生拼接,当两个value都有值的情况下才需要拼接
            // 展示多少个拼接,就返回多少个元素
        ]
    },
    // 设备故障信息
    "errorStatus": {
        "isError": true, // true:设备故障;false:无故障。状态岛计算以设备为维度,单个设备,多个错误码,计数+1
        "errorCode": "E1", // 错误码,String;多个错误码,以,连接,eg:E1,E2
    }
}

# 控制指令传参

  • 在设备状态的Object中,增加setValue字段,作为共同参数传入脚本执行方法,得出执行指令集 控制代码示例
  • 控制指令输入示例
{
    "deviceId": "24189255812085",
    "deviceSn": "000000P0000000Q1A0681CAE921C0000",
    "deviceSn8": "00000Q1A",
    "deviceStatus": {"xxx": "xxx"},
    "isOnline": "1",
    "regionCode": "US",
    "setValue": 16, // 一级功能控制入参
    "setValue": {"value": 25}, // 二级功能viewType=0/1时控制入参,
    "setValue": {"xxx": "xxx", "controlValue": "xxx"}, // 二级功能viewType=2时控制入参,内容为items被选中元素
    "setValue": [70, 74], // 温控器特殊模块控制入参
}
  • 控制指令输出示例
"backData" = {
    // controlParams有多少个元素即下发多少次指令。
    "controlParams": [{
        "applianceCode": "设备id,从原生传入的设备状态中获取",
        // lua控制指令
        "key": "value"
    }, {
        "applianceCode": "设备id,从原生传入的设备状态中获取",
        // lua控制指令
        "key": "value"
    }]
}