本文档面向已经了解 面板小程序开发 的开发者,你需要充分的了解什么是面板小程序 产品功能 若您对上述概念有所疑问,我们推荐你去看一些预备知识。如果您已了解,可跳过本文。

理解关系

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

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

电工模板使用 SDM(Smart Device Model) 开发,关于 SDM 相关可以 查看 SDM 文档

相关概念

产品名称:通用电工插座

产品介绍

提供插座的打开与关闭的基本功能,并提供关闭倒计时、增加电量、更新当前电流、功率参数等功能,根据以下通用电工的开发教程帮助您开发面板小程序去控制插座。

需求原型

  1. 首页 点击中间按钮切换 switch_1 开关状态。

  1. 首页 页面展示倒计时提示,根据开关状态、手机系统的 24 小时制或 12 小时制、countdown_1 的值来显示对应的提示文案,若未设置倒计时则不展示。
  2. 点击首页底部倒计时 弹出倒计时提示框组件来设置倒计时,若未设置则展示设置倒计时的组件,若已设置则可关闭倒计时。

  1. 点击首页底部统计进入电量统计页面,会展示今日电量当前电流当前电压当前功率日月年维度的图表,并支持导出日月年维度的数据到指定邮箱

  1. 点击首页底部设置进入设置页面,可以对除 switch_1countdown_1 的所有 可下发可上报(rw)功能进行设置。

功能汇总

当前电工插座模板必须的功能点:

switch_1,
countdown_1,

DP 功能

dp 功能

dpid

code

type

mode

property

开关

1

switch_1

布尔型(Bool)

可下发可上报(rw)

倒计时

9

countdown_1

数值型(Value)

可下发可上报(rw)

数值范围: 0-86400, 间距: 1, 倍数: 0, 单位: s

增加电量

17

add_ele

数值型(Value)

可下发可上报(rw)

数值范围: 0-50000, 间距: 100, 倍数: 3, 单位: kwh

当前电流

18

cur_current

数值型(Value)

可下发可上报(rw)

数值范围: 0-80000, 间距: 1, 倍数: 0, 单位: mA

当前功率

19

cur_power

数值型(Value)

只上报(ro)

数值范围: 0-200000, 间距: 1, 倍数: 1, 单位: W

当前电压

20

cur_voltage

数值型(Value)

只上报(ro)

数值范围: 0-5000, 间距: 1, 倍数: 1, 单位: V

上面为首页需求必须的功能点,设置页功能点这里不做介绍。

首先需要创建一个电工类产品,定义产品有哪些功能点,然后面板中再根据这些功能点一一实现。

进入IoT 平台,点击左侧产品菜单,产品开发,创建产品,选择标准类目 -> 电工 -> 插座:

选择功能点,这里我们只需要默认的标准功能即可。

选择高级功能,这里需要把电量统计基础版开启。

🎉 在这一步,我们创建了一个名为 PublicSocket的电工插座产品。

开发者平台创建面板小程序

这部分我们在 小程序开发者 平台上进行操作,注册登录 小程序开发者平台

订阅统计及日志云能力

在开发者平台,选择创建好的面板小程序,进入小程序管理页面,选择开发设置进入开发设置页面,在云能力模块中找到小程序设备日志能力及小程序图表能力,然后订阅它们。

创建 IDE 项目

打开 IDE,选择新建,输入项目名称,关联创建的面板小程序,选择单插产品,然后点击下一步

在下一步中,找到电工单插模板,并完成创建项目

此时,回到项目管理列表,选择刚创建好的项目,进入后,即可进行预览并开发。

工程目录

上面的步骤我们已经初始化好了一个面板小程序的开发模板,下面我们介绍下工程目录。

├── src
│ ├── app.config.ts # 自动生成配置
│ ├── app.tsx # App 根组件
│ ├── components # 组件目录
│ ├── constant # 常量目录
│ ├── devices # 智能设备模型目录
│ │ ├── index.ts # 定义并导出智能设备模型
│ │ └── schema.ts # 当前智能设备 DP 功能点描述,IDE 可自动生成
│ ├── global.config.ts
│ ├── hooks # 自定义 hooks 目录
│ ├── i18n # 多语言目录
│ ├── pages # 页面目录
│ └── routes.config.ts # 路由配置
│─── typings #业务类型定义目录
│ └── sdm.d.ts #智能设备类型定义文件

需求实现

1. IDE 生成 SDM schema到项目。

生成 SDM schema 至项目中,可以查看 src/devices/schema.ts

export const defaultSchema = [
  {
    attr: 1024,
    canTrigger: true,
    code: 'switch_1',
    defaultRecommend: false,
    editPermission: true,
    executable: true,
    extContent: '',
    iconname: 'icon-dp_power2',
    id: 1,
    mode: 'rw',
    name: '开关1',
    property: {
      type: 'bool',
    },
    type: 'obj',
  },
  {
    attr: 1120,
    canTrigger: false,
    code: 'countdown_1',
    defaultRecommend: false,
    editPermission: true,
    executable: false,
    extContent: '',
    iconname: 'icon-dp_time2',
    id: 9,
    mode: 'rw',
    name: '开关1倒计时',
    property: {
      unit: 's',
      min: 0,
      max: 86400,
      scale: 0,
      step: 1,
      type: 'value',
    },
    type: 'obj',
  },
  {
    attr: 1120,
    canTrigger: false,
    code: 'add_ele',
    defaultRecommend: false,
    editPermission: true,
    executable: false,
    extContent: '{"trigger":"direct"}',
    iconname: 'icon-battery',
    id: 17,
    mode: 'rw',
    name: '增加电量',
    property: {
      unit: 'kwh',
      min: 0,
      max: 50000,
      scale: 3,
      step: 100,
      type: 'value',
    },
    type: 'obj',
  },
  {
    attr: 1088,
    canTrigger: true,
    code: 'cur_current',
    defaultRecommend: false,
    editPermission: true,
    executable: false,
    extContent: '',
    iconname: 'icon-Ele',
    id: 18,
    mode: 'ro',
    name: '当前电流',
    property: {
      unit: 'mA',
      min: 0,
      max: 80000,
      scale: 0,
      step: 1,
      type: 'value',
    },
    type: 'obj',
  },
  {
    attr: 1088,
    canTrigger: true,
    code: 'cur_power',
    defaultRecommend: false,
    editPermission: true,
    executable: false,
    extContent: '',
    iconname: 'icon-dp_tool',
    id: 19,
    mode: 'ro',
    name: '当前功率',
    property: {
      unit: 'W',
      min: 0,
      max: 200000,
      scale: 1,
      step: 1,
      type: 'value',
    },
    type: 'obj',
  },
  {
    attr: 1088,
    canTrigger: true,
    code: 'cur_voltage',
    defaultRecommend: false,
    editPermission: true,
    executable: false,
    extContent: '',
    iconname: 'icon-a_function_turbo',
    id: 20,
    mode: 'ro',
    name: '当前电压',
    property: {
      unit: 'V',
      min: 0,
      max: 5000,
      scale: 1,
      step: 1,
      type: 'value',
    },
    type: 'obj',
  },
];

2. 需求 -首页 点击中间按钮切换 switch_1 开关状态

分析需求:

  1. 首页添加组件 开关按钮
    1. 根据 switch_1 下发的值展示不同按钮图片。
    2. 点击开关组件触发事件,上报「开」「关」的 dp 值。
  2. 确认开关 dp 为switch_1,可作为属性传入组件。
  3. 使用 useProps 获取实时下发的 dp 值。示例:
    import React from 'react';
    import { View } from '@ray-js/ray';
    import { useProps } from '@ray-js/sdm-react';
    
    export default function () {
      const switch_1 = useProps((dpState) => dpState.switch_1);
      return (
        <View style={{ flex: 1 }}>
          <View>switch_1: {switch_1}</View>
        </View>
      );
    }
    
  4. 使用 useActions 获取dp上报的行为示例:
    import React from 'react';
    import { View } from '@ray-js/ray';
    import { useActions } from '@ray-js/sdm-react';
    
    export default function () {
      const actions = useActions();
      return (
        <View style={{ flex: 1 }}>
          <Button
            onClick={() => {
              actions.switch_1.set(false);
            }}
          >
            change action
          </Button>
        </View>
      );
    }
    

根据上述分析,我们来实现开关组件。

import React from 'react';
import clsx from 'clsx';
import { View } from '@ray-js/ray';
import { DpBooleanAction } from '@tuya-miniapp/sdm';
import { useProps, useActions } from '@ray-js/sdm-react';
import { Icon } from '@/components/icon';
import { icons } from '@/res';
import styles from './index.module.less';

export interface Props {
  dpCode: string;
}

export const PowerButton = React.memo<Props>(props => {
  const { dpCode } = props;
  const value = useProps(dpState => dpState[dpCode]);

  const actions = useActions();

  if (!dpCode || typeof value !== 'boolean') {
    return null;
  }

  const action = actions[dpCode] as DpBooleanAction;

  return (
    <View className={styles['power-button']} onClick={action.toggle}>
      <View
        className={clsx(styles['power-button-content'], {
          [`${styles['power-button-off']}`]: !value,
        })}
      />
      <Icon
        className={styles['power-button-icon']}
        d={icons.power}
        size="34px"
        fill={value ? '#ef550d' : '#ffffff'}
      />
    </View>
  );
});

引入了代码之后,我们的首页有了一个可操控的按钮,这时我们可以修改 IDE右侧控制面板 -> 1.开关 -> false/true 进行虚拟面板dp点的下发与上报,也可以点击我们刚刚完成的组件,查看IDE 控制面板的状态来验证我们的产品功能。

1. 首页 页面展示倒计时提示,根据开关状态、手机系统的 24 小时制或 12 小时制、countdown_1 的值来显示对应的提示文案,若未设置倒计时则不展示。

  1. 创建倒计时提示组件,根据 开关状态 switch_1 及倒计时 countdown_1 状态下发的值来控制展示内容。

倒计时提示组件实现

2. 点击首页底部倒计时 弹出倒计时提示来设置倒计时,若未设置则展示设置倒计时的组件,若已设置则可关闭倒计时。

  1. 创建底部 Tab 组件及倒计时弹窗组件,根据 倒计时 countdown_1 状态下发的值来控制展示内容。
  2. 通过 useActions 上报 倒计时 countdown_1的状态。

倒计时弹窗组件实现

3. 点击首页底部统计进入统计页面,可以显示当前电流当前电压当前功率数据,并获取统计数据,获取统计相关接口可参数这里

统计页面实现

4. 点击首页底部设置进入设置页面,可以对除 switch_1countdown_1 的所有 可下发可上报(rw)功能进行设置。

  1. 设置页面展示所有 可下发可上报(rw)的功能并进行设置。
  2. 通过 useDevice 获取全部 功能点 dp
    import { useDevice } from '@ray-js/sdm-react';
    const { devInfo } = useDevice();
    // 获取到全部 dp schema
    const dpSchemas = devInfo.schema;
    
  3. 根据不同功能点 dp的类型进行展示不同 UI 及交互弹窗。

设置页面实现

5. 在设备页面点击开关日志进入日志页面,这里使用了获取上报记录的 api

日志页面实现