面板作为 IoT 智能设备在 App 终端上的产品形态,创建产品之前,首先来了解一下什么是面板,以及和产品设备之间的关系。

1.1 面板是什么?

  1. 面板 是运行在智能生活 AppOEM App(涂鸦定制 App) 上的界面交互程序,用于控制 智能设备 的运行,展示 智能设备 实时状态。
  2. 产品面板智能设备 联系起来,产品描述了其具备的功能、在 App 上面板显示的名称、智能设备拥有的功能点等。
  3. 智能设备 是搭载了 涂鸦智能模组 的设备,通常在设备上都会贴有一张 二维码,使用 智能生活 App 扫描二维码,即可在 App 中获取并安装该设备的控制 面板

1.2 产品、面板、设备关系

下图描述了产品、面板和设备三者之间的关系

1.3 创建产品

由于产品定义了面板和设备所拥有的功能点,所以在开发一个智能设备面板之前,我们首先需要创建一个产品,定义产品有哪些功能点,然后面板中再根据这些功能点一一实现。

这部分我们在 IoT 平台上进行操作,注册登录 IoT 平台:

  1. 点击左侧产品菜单,产品开发,创建产品,以大家电为例,选择标准类目,选择大家电 -> 空调:

  1. 填写产品名称,输入"万能面板",其余选项默认即可,点击创建产品按钮,完成产品创建。

创建完成产品后,进入功能定义页面,这里列出了空调类目下可选的标准功能点,这里我们点击全部选择,点击确定完成产品初始功能点设置:

现在我们已经有了一个产品,并且功能点已设置完成,接下来就进入面板小程序的开发流程。前往注册登录涂鸦小程序开发者平台,创建我们的小程序项目。

点击新建,输入小程序名称"万能面板",小程序类型选择 面板小程序,面板类型选择公版,点击确定完成创建:

安装并打开小程序 IDE 工具(前往下载小程序 IDE

使用涂鸦 IoT 平台账号登录 IDE:

4.1 创建项目代码

点击新建,输入项目名称:万能面板,关联智能小程序选择第 3 步小程序平台创建的小程序,关联产品选择第 1 步在 IoT 平台创建的产品:

点击下一步选择模版,选择 小程序面板模版 ReduxToolkit,生成 Ray 面板项目(Ray 类似 Taro,是一个多端研发框架,编写一套代码编译到多端)

4.2 启动项目

进入项目后,需要使用 智能生活 App 授权登录,

登录后,项目会重新编译加载。

涂鸦小程序 IDE 工具导入小程序后会自动安装依赖,并实时编译运行。

如果出现Error(MiniKit 不存在指定的版本 2.3.3)类似的错误,点击环境配置 -> Kit 管理,选择推荐的版本即可:

此时控制台 console 会提示 deviceId 错误的信息,这是因为我们还没有关联产品,点击工具栏打开 面板工具

进入面板工具后,点击添加虚拟设备,然后使用 智能生活 App 扫描二维码:

扫描完成后,项目会拉取产品信息并重新加载项目,即可拉取出设备信息

选择产品后,

面板小程序开发主要围绕 IoT 平台、小程序开发平台、小程序 IDE 之间进行,用一张图来概括整体流程:

以上完成了一个面板小程序的创建流程,下面进入到实际代码的开发教程。

6.1 代码目录结构

首先了解项目的目录结构,点击工具栏在 vscode 打开项目代码:

然后在 vscode 中可以看到项目代码的文件目录结构:

6.2 页面路由配置

编写代码主要在 pages 文件夹中进行,创建你的页面代码,然后将路由地址配置到 src/routes.config.ts 文件中:

其他文件的说明,会在下文开发步骤中顺路提到。

7.1 使用 SDM 智能设备模型状态管理读取设备数据

查看 SDM 智能设备模型文档

在 IDE 中点击 在 vscode 打开 按钮,打开 vscode 编辑器,

在 src/app.tsx 中提供一个 SdmProvider 用来初始化设备信息:

// 创建 SDM 智能设备模型
const value = new SmartDeviceModel({ deviceId });

value.init(); // 执行初始化

// 初始化完成事件
value.onInitialized(() => {
	// 初始化完成后可以进行设备信息获取和操作
	// 如 value.getDpSchema()
	// ....
});

在 src/app.tsx 应用根组件设置如下,使用 SdmProvider 将智能设备模型实例放在 context 中:

import {
	SdmProvider,
	SmartDeviceModel,
	SmartGroupModel,
} from "@ray-js/panel-sdk";
import { initPanelEnvironment } from "@ray-js/ray";

initPanelEnvironment({ useDefaultOffline: true });

class App extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			model: null,
		};
	}

	onLaunch(object) {
		const { query = {} } = object;
		const { groupId, deviceId } = query;

		if (groupId || deviceId) {
			value = groupId
				? new SmartGroupModel({ groupId })
				: new SmartDeviceModel({ deviceId });

			value.init();
			value.onInitialized(() => {
				this.setState({
					model: value,
				});
			});
		}
	}

	render() {
		if (this.state.model) {
			return (
				<SdmProvider value={this.state.model}>
					{this.props.children}
				</SdmProvider>
			);
		}
	}
}

修改 src/pages/home/index.tsx 文件,输入以下代码:

import React from "react";

import { useDpSchema, useProps } from "@ray-js/panel-sdk";
import { View } from "@ray-js/ray";

export default () => {
  // 项目启动时,会自动拉取 IoT 平台 productId 对应的产品 schema 信息
  const dpSchema = useDpSchema();

  // 从设备模型中读取 dpState 数据
  const dpState = useProps(state => state); // 获取所有dpState
  const switch = useProps(state => state.switch); // 获取dpCode为switch的值

  console.log("dpSchema", dpSchema); // 打印查看 dpSchema 内容
  console.log("dpState", dpState); // 打印查看 dpState 内容

  return <View>hello world</View>;
};

注意 useProps 使用时,建议精确到读取哪个 dp,例如精确到读取 switch state => state.switch,只有当 switch 变化时组件才会重新渲染

7.2 IDE 调试器 console 打印日志

查看 IDE 调试 console,可以看到打印出 devInfo 内容:

代码中获取 devInfo:

import { useDevInfo } from "@ray-js/panel-sdk";

const devInfo = useDevInfo();
console.log("devInfo:", devInfo);

7.3 devInfo 字段说明

IDE 调试器 console 面板中默认可以看到有很多输出,其中最重要的就是 devInfo ,即设备信息(Device Information

需要了解 devInfo 中几个重要的属性,

  1. codeIds: 一个对象,key 是 dpCode,值是 dpId
  2. devId: 设备的 id,虚拟设备会以 vdevo 开头
  3. deviceOnline: 设备是否在线
  4. dps: 一个对象,keydpId,值是 DP 的状态
  5. idCodes: 一个对象,与 codeIds 相反
  6. panelConfig: 面板配置,其中 bic 是云功能配置
  7. productId: 当前设备绑定的产品
  8. schema: 产品的功能点定义,其中描述了 DPcode、类型、值范围属性、icon 图标
  9. state: 一个对象,keydpCode,值是 DP 的状态
  10. ui: 面板的 uiId

通常代码中获取 devInfo 是通过 useDevInfo API 来读取。(本文中的 DP功能点,来自 IoT 平台功能定义)

7.4 获取产品功能定义(schema)

使用 useDpSchema 可以获取到产品的功能定义

import { useDpSchema, useProps } from "@ray-js/panel-sdk";

const dpSchema = useDpSchema(); // 功能点定义
const dpState = useProps((state) => state); // 设备功能点状态

遍历 schema 可以获取到产品所有的 DP 功能点及属性:

schema.map((item) => {
	// item.code
	// item.property
	// ...
	return <Text>{item.name}</Text>;
});

这里根据 item.property.type 就可以判断并渲染不同类型 DP 功能点的 UI 展示

8.1 使用 rpx 单位

Ray 开发样式使用 less 语言,支持 css module,新建文件 index.module.less,编写内容例如:

src/pages/home/index.module.less

.container {
	border-radius: 24rpx;
	background-color: #fff;
	margin-bottom: 24rpx;
}

rpx 单位是 Ray 框架提供的特有单位,能够做到不同设备上的自适应。

8.2 使用 css module 方式添加样式

在代码中使用样式:

import React from "react";

import { useDpSchema } from "@ray-js/panel-sdk";
import { View } from "@ray-js/components";
import styles from "./index.module.less"; // 注意样式引入方式

export default () => {
	const dpSchema = useDpSchema();

	// 添加 className
	return <View className={styles.container}>hello world</View>;
};

9.1 功能定义 Schema 的结构

通过 console 日志可以了解到 schema 的数据结构:

详细请参考文档 自定义功能

9.2 渲染 Schema 数据展示

src/home/index.tsx 编写输入以下代码:

import React from "react";

import { useDevInfo, useDpSchema, useProps } from "@ray-js/panel-sdk";
import { View } from "@ray-js/components";

export default () => {
	const dpSchema = useDpSchema();
	const dpState = useProps((state) => state);

	console.log("dpSchema", dpSchema);
	console.log("dpState", dpState);

	return (
		<View>
			{Object.keys(dpSchema || {}).map((dpCode) => {
				// 遍历渲染每个功能点
				return (
					<View key={dpCode}>
						{dpCode}: {dpState[dpCode]}
					</View>
				);
			})}
		</View>
	);
};

重新编译,可以看到 IDE 左边面板中显示了所有 DPcode 及对应设备状态 :

10.1 bool 功能点数据结构

在 IDE console 面板中,可以看到 bool 类型功能点的数据结构,例如:

{
	dptype: "obj";
	id: "39";
	type: "bool";
}

10.2 安装扩展组件库

使用工具包 @ray-js/components-ty 提供的开关组件 TySwitch 来渲染,执行以下命令,安装 Ray 提供的扩展组件库:

yarn add @ray-js/components-ty

10.3 使用开关组件 TySwitch

继续编写代码,输入以下内容:

import React from "react";

import { useDpSchema } from "@ray-js/panel-sdk";
import { TySwitch } from "@ray-js/components-ty";
import { View } from "@ray-js/components";

const BoolCard = ({ dpCode }) => {
	const dpValue = useProps((state) => state[dpCode]);
	const actions = useActions();
	return (
		<View>
			{dpCode}:{" "}
			<TySwitch
				checked={dpValue}
				onChange={() => {
					actions[dpCode].toggle();
				}}
			/>
		</View>
	);
};

export default () => {
	const dpSchema = useDpSchema();
	const dpState = useProps((state) => state);

	console.log("dpSchema", dpSchema);

	return (
		<View>
			{Object.keys(dpSchema || {}).map((dpCode) => {
				const props = dpSchema[dpCode];
				// 判断如果是 bool 类型,返回 TySwitch
				if (props.type === "bool") {
					return <BoolCard dpCode={dpCode} />;
				}
				return (
					<View key={dpCode}>
						{dpCode}: {dpState[dpCode]}
					</View>
				);
			})}
		</View>
	);
};

编译后,IDE 中渲染界面如下,看到所有的 bool 型 DP 已经成功渲染出了开关组件

10.4 功能点多语言获取

DP 在功能定义时,在产品信息中已经有相应的多语言文本,这里使用 src/i18n 下的 Strings 工具获取 DP 文本,输入以下代码:

import React from "react";

import { useDpSchema, useProps } from "@ray-js/panel-sdk";
import { TySwitch } from "@ray-js/components-ty";
import { View } from "@ray-js/components";
import Strings from "@/i18n";

export default () => {
	const dpSchema = useDpSchema();
	const dpState = useProps((state) => state);

	console.log("dpSchema", dpSchema);

	return (
		<View>
			{Object.keys(dpSchema || {}).map((dpCode) => {
				const props = dpSchema[dpCode];
				if (props.type === "bool") {
					// 使用 Strings.getDpLang 方法获取多语言
					return (
						<View>
							{Strings.getDpLang(dpCode)}:{" "}
							<TySwitch checked={dpState[dpCode]} />
						</View>
					);
				}
				return (
					<View key={dpCode}>
						{dpCode}: {dpState[dpCode]}
					</View>
				);
			})}
		</View>
	);
};

再次编译查看 IDE 渲染结果,可以看到所有的 bool 类型 DP 文本都已显示出中文:

这样就完成了 Bool 类型 DP 功能点的 UI 渲染。

11.1 使用下发 DP 功能点 API

上文介绍了如何编写代码渲染 DP 点,但是要控制设备运行,还需要进行 DP 下发, 使用 SDM 智能设备模型 提供的 hooks useActions 下发能力,例如:

import { useActions } from "@ray-js/panel-sdk";

const actions = useActions();

// 下发给对应设备,actions.xxx 中的 xxx 是 dpCode,set 是下发指令的方法,传入dpValue调用即可下发指令
actions.switch.set(true); // 下发 switch 为 true
actions.switch.on(); // 打开当前布尔类型功能点
actions.switch.off(); // 关闭当前布尔类型功能点
actions.switch.toggle(); // 在 true 和 false 之间切换 bool 值

11.2 下发 Bool 开关功能点

现在来示例开关功能点的 DP 下发 操作,编写代码:

首先实现 Bool 下发上报组件:

import React from "react";

import { useActions, useProps } from "@ray-js/panel-sdk";
import { View } from "@ray-js/components";

const BoolCard = ({ dpCode }) => {
	const actions = useActions();
	const dpValue = useProps((state) => state[dpCode]);
	return (
		<View>
			{dpCode}:{" "}
			<TySwitch checked={dpValue} onChange={() => actions[dpCode].toggle()} />
		</View>
	);
};

对于 bool 类型的 DP 功能点,actions.xxx 会有以下几个工具方法:

如 switch 开关 DP 点的 actions:

actions.switch.on; // switch 功能点下发 true
actions.switch.off; // switch 功能点下发 false
actions.switch.toggle; // switch 功能点下发 false
export default () => {
	const schema = useDpSchema();
	const dpState = useProps((state) => state);
	const actions = useActions();

	return (
		<View>
			{Object.keys(schema || {}).map((dpCode) => {
				const props = schema[dpCode];
				// 判断如果是 bool 类型,返回 TySwitch
				if (props.type === "bool") {
					return <BoolCard key={dpCode} dpCode={dpCode} />;
				}
				return (
					<View key={dpCode}>
						{dpCode}: {dpState[dpCode]}
					</View>
				);
			})}
		</View>
	);
};

11.3 虚拟设备插件调试

IDE 编译后运行,使用虚拟设备插件进行调试,在调试器 Virtual Device 面板中,选择可视化面板,点击调试器中的开关,可以看到左边模拟器中的开关收到了 DP 上报,并做出了相同的切换动作。

12.1 enum 功能点数据结构

enum 类型 DP 点的 schema 属性配置如下:

{
	dptype: "obj";
	id: "20";
	range: ["cancel", "1h", "2h", "3h", "4h", "5h", "6h"];
	type: "enum";
}

12.2 使用弹窗组件 TyActionsheet 和列表组件 TyCell

range 中的即枚举条目,使用 @ray-js/components-ty 中的 ActionSheet 弹窗组件 + Cell 列表组件 进行渲染,编写以下代码:

首先实现 Enum 枚举展示控制组件:

import React from "react";

import { useActions, useProps } from "@ray-js/panel-sdk";
import { View } from "@ray-js/components";
import Strings from "@/i18n";

const EnumCard = ({ dpCode }) => {
	const actions = useActions();
	const dpValue = useProps((state) => state[dpCode]);

	const [showEnumDp, setShowEnumDp] = useState(null);

	return (
		<View>
			{Strings.getDpLang(dpCode)}:
			<Button onClick={() => setShowEnumDp(dpCode)}>
				{Strings.getDpLang(dpCode, dpState[dpCode])}
			</Button>
			<TyActionsheet
				header={Strings.getDpLang(dpCode)}
				show={showEnumDp === dpCode}
				onCancel={() => setShowEnumDp(null)}
			>
				<View style={{ overflow: "auto", height: "200rpx" }}>
					<TyCell.Row
						rowKey="title"
						dataSource={props.range.map((item) => ({
							title: Strings.getDpLang(dpCode, item),
							onClick: () => {
								actions[dpCode].set(item);
							},
						}))}
					/>
				</View>
			</TyActionsheet>
		</View>
	);
};

对于 enum 类型的 DP 功能点,actions.xxx 会有以下几个工具方法:

如 work_mode 开关 DP 点的 actions:

actions.work_mode.set("white"); // work_mode 下发 white
actions.work_mode.next(); // 切换下一个枚举
actions.work_mode.prev(); // 切换下一个枚举
actions.work_mode.random(); // 切换到随机一个枚举值

遍历 schema 渲染

import React, { useState } from "react";

import { useDpSchema, useProps } from "@ray-js/panel-sdk";
import { TyActionsheet, TyCell, TySwitch } from "@ray-js/components-ty";
import { Button, ScrollView, View } from "@ray-js/components";
import Strings from "@/i18n";

export default () => {
	const schema = useDpSchema();
	const dpState = useProps((state) => state);

	console.log("schema", schema);

	const [showEnumDp, setShowEnumDp] = useState(null);

	return (
		<View>
			{Object.keys(schema).map((dpCode) => {
				const props = schema[dpCode];
				// 这里为了文章篇幅,忽略其他类型的。本地代码可复制上节 bool 类型的到这里
				if (props.type === "enum") {
					return <EnumCard key={dpCode} dpCode={dpCode} />;
				}
				return (
					<View key={dpCode}>
						{dpCode}: {dpState[dpCode]}
					</View>
				);
			})}
		</View>
	);
};

点击按钮,触发 ActionSheet 弹窗,弹窗中使用 Cell 列表组件 渲染多个枚举项,效果如下:

13.1 string 功能点数据结构

string 类型 DP 点的 schema 属性配置如下:

{
	dptype: "obj";
	id: "20";
	type: "string";
}

13.2 使用输入组件 Input

首先实现 Input 输入组件:

import React from "react";

import { useActions, useProps } from "@ray-js/panel-sdk";
import { Input } from "@ray-js/components";
import Strings from "@/i18n";

const InputCard = ({ dpCode }) => {
	const actions = useActions();
	const dpValue = useProps((state) => state[dpCode]);

	const [showEnumDp, setShowEnumDp] = useState(null);

	return (
		<Input
			value={dpState[dpCode]}
			onInput={(event) => {
				actions[dpCode].set(event.detail.value);
			}}
		/>
	);
};

对于 string 类型的 DP 功能点,actions.xxx 会有以下几个工具方法:

如 name 名称 DP 点的 actions:

actions.name.set("my device"); // name 下发 my device

遍历 schema 渲染

import { useDpSchema, useActions } from "@ray-js/panel-sdk";
import { Input } from "@ray-js/components";

export default () => {
	const schema = useDpSchema();
	const dpState = useProps((state) => state);

	console.log("schema", schema);

	return (
		<View>
			{Object.keys(schema || {}).map((dpCode) => {
				const props = schema[dpCode];
				// 这里为了文章篇幅,忽略其他类型的。本地代码可复制上节类型的到这里
				if (props.type === "string") {
					return <InputCard value={dpState[dpCode]} />;
				}
				return (
					<View key={dpCode}>
						{dpCode}: {dpState[dpCode]}
					</View>
				);
			})}
		</View>
	);
};

Raw 类型 DP 一般不做渲染,如果需要可以按照 String 类型进行处理

14.1 value 功能点数据结构

value 类型 DP 点的 schema 属性配置如下:

{
	dptype: "obj";
	id: "18";
	max: 100;
	min: 0;
	scale: 0;
	step: 1;
	type: "value";
	unit: "%";
}

14.2 使用滑动条组件 Slider

首先实现 Input 输入组件:

其中定义了数值范围和单位,使用 Slider 组件进行渲染:

import React from "react";

import { useActions, useProps } from "@ray-js/panel-sdk";
import { Slider } from "@ray-js/components";
import Strings from "@/i18n";

const ValueCard = ({ dpCode }) => {
	const actions = useActions();
	const dpValue = useProps((state) => state[dpCode]);

	return (
		<View>
			{Strings.getDpLang(dpCode)}:
			<Slider
				step={props?.step}
				max={props?.max}
				min={props?.min}
				value={dpState[dpCode]}
				onChange={(event) => {
					actions[dpCode].set();
				}}
			/>
		</View>
	);
};

对于 value 类型的 DP 功能点,actions.xxx 会有以下几个工具方法:

如 add_ele 用电量 DP 点的 actions:

actions.add_ele.set(1000); // add_ele 下发 1000
actions.add_ele.inc(); // 根据当前功能点步长 step 进行递增
actions.add_ele.dec(); // 根据当前功能点步长 step 进行递减

遍历 schema 渲染

import { useDpSchema, useActions, useProps } from "@ray-js/panel-sdk";
import { Slider } from "@ray-js/components";

export default () => {
	const schema = useDpSchema();
	const dpState = useProps((state) => state);

	console.log("schema", schema);

	return (
		<View>
			{Object.keys(schema).map((dpCode) => {
				const props = schema[dpCode];
				// 这里为了文章篇幅,忽略其他类型的。本地代码可复制上节类型的到这里
				if (props.type === "value") {
					return <ValueCard dpCode={dpCode} />;
				}
				return (
					<View key={dpCode}>
						{dpCode}: {dpState[dpCode]}
					</View>
				);
			})}
		</View>
	);
};

Slider 组件是一个滑动条组件,可以根据数值范围进行约束,IDE 渲染如下,所有 value 类型 DP 都渲染出了滑动条:

15.1 bitmap 功能点数据结构

bitmap 类型一般用作故障上报,属性配置如下:

{
	dptype: "obj";
	id: "22";
	label: ["sensor_fault", "temp_fault"];
	maxlen: 2;
	type: "bitmap";
}

15.2 使用消息提醒组件 Notification

故障型 DP 使用弹窗渲染,这里使用 @ray-js/ray-components-plus 提供的 Notification 来实现:

import { useDpSchema, useActions, useProps } from "@ray-js/panel-sdk";
import { Notification } from "@ray-js/ray-components-plus";

export default () => {
	const schema = useDpSchema();
	const dpState = useProps((state) => state);

	console.log("schema", schema);

	// 弹窗消息在 useEffect 中进行
	useEffect(() => {
		Object.keys(schema).forEach((dpCode) => {
			const props = schema[dpCode];
			if (props.type === "bitmap") {
				Notification.show({
					message: Strings.getFaultStrings(dpCode, dpState[dpCode]),
					icon: "warning",
				});
			}
		});
	}, [schema, dpState]);

	return (
		<View>
			{Object.keys(schema).map((dpCode) => {
				const props = schema[dpCode];
				// 这里为了文章篇幅,忽略其他类型的。本地代码可复制上节类型的到这里
				return (
					<View key={dpCode}>
						{dpCode}: {dpState[dpCode]}
					</View>
				);
			})}
		</View>
	);
};

bitmap 类型通常用来做故障上报,以弹窗消息提示,所以需要在 useEffect 中遍历 schema 找到 bitmap 类型并弹窗提醒。

16.1 IoT 平台添加自定义功能点

以上 schema 中是家电类目自带的标准 DP 点,我们还可以增加自定义的 DP,打开 IoT 平台产品详情 -> 功能定义 -> 自定义功能 一栏,

16.2 自定义功能点属性配置

点击添加功能,新建一个 bool 型 DP:

16.3 IDE 刷新拉取自定义功能点配置

然后回到 IDE 中,点击编译按钮刷新面板,可以看到渲染出了我们新增加的一个 DP 点:

17.1 虚拟设备解决什么问题?

面板运行时需要获取设备信息来显示设备的运行状态,在开发阶段,如果没有真实的智能硬件设备,我们可以借助虚拟设备来辅助调试,可以达到和真实设备一样的效果。虚拟设备和真实设备对于面板小程序来说可以是等效的,其关系如下图所示:

17.2 授权 IDE 登录

在使用虚拟设备前,请先确认已授权登录态,点击右上角登录,使用智能生活 App 扫描二维码授权登录。

16.3 App 扫码创建虚拟设备

登录后进入万能面板项目,点击调试工具 Virtual Device,使用智能生活 App 扫码创建虚拟设备:

17.4 操作指南

虚拟设备面板中分为 3 个区块,左边是兜底面板用于展示当前产品的 DP 功能点,右侧是虚拟设备 DP 控制列表,可以改变 DP 状态然后点击上报按钮,下方是 Log 面板用于输出 MQTT 日志。点击"可视化面板",切换到兜底面板视图,与控制面板功能相同,更加直观的展现产品功能点。

17.5 调试我们编写的代码!

下面来调试我们刚编写的代码:

18.1 获取虚拟设备 ID

在虚拟设备界面右侧 -> 设备信息,点击 deviceId 右侧的复制按钮

18.2 设置真机调试参数

点击编译参数设置,按照格式填入真机调试参数。 例如:deviceId=vdevo165398364416684

18.3 App 扫码打开调试器

设置好编译参数后,点击真机调试按钮(真机需要前往下载智能生活 App

使用智能生活 App 扫描二维码,打开并进入小程序面板,可以在真机上进行调试万能面板。

到此你已经熟悉了 6 种 DP 点的渲染及下发,附上万能面板代码开源地址:

panel-universal

经过样式优化后的万能面板展示:

20.1 上传源码包

IDE 中完成调试后,点击上传源码按钮,输入版本号及说明,点击上传预览包

上传完成后,在小程序开发者平台版本管理中可以看到已经上传的版本列表

20.2 添加预览包白名单

在上传完成源码包后,在小程序开发者平台 -> 版本管理中,选择需要预发布的版本,设为体验版:

点击白名单页面,添加自己智能生活 App 的账号:

添加完后,可以点击 版本管理 -> 体验二维码,查看小程序码,使用智能生活 App 扫码预览小程序。

20.3 审核上线

非官方主体的面板小程序,在提交审核前需要完善 IoT 平台展示信息。其余审核上线注意项可参考:上线审核