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

理解关系

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

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

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

相关概念

产品名称:智能摄像机

需求原型

  1. 主题切换:支持明暗主题,自动跟随 App
  2. 播放器模块:支持预览、录制、截屏、对讲、音频、电量、横屏等集合
  3. 运营模块:可配置服务营销信息与产品运营内容
  4. 功能入口:可配置展示摄像机重要功能入口如相册、云台等
  5. 更多功能:可配置低频隐私模式、WDR、巡航、灯开关等
  6. 快捷操作栏:可配置如回放、对讲、消息等高频重点或特色功能

暗黑主题

明亮主题

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

进入IoT 平台,点击左侧产品菜单,产品开发,创建产品,选择标准类目 -> 摄像机 -> 云台摄像机:

选择功能点,这里根据自己需求选择即可,这些功能未选择不影响视频预览。

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

面板小程序的开发在 小程序开发者 平台上进行操作,首先请前往 小程序开发者平台 完成平台的注册登录。

详细操作步骤可以参考 面板小程序 > 创建面板小程序

2. IDE 基于模板创建项目工程

打开 IDE 创建一个基于 IPC 通用模板 的面板小程序项目,需要在 Tuya MiniApp IDE 上进行操作。

详细操作步骤可以参考 面板小程序 > 初始化项目工程

3. 从模板仓库导入项目工程

您也可以通过 GitHub 仓库拉取模板源码,自主导入 IDE:

🔗 模板仓库地址
https://github.com/Tuya-Community/tuya-ray-materials

步骤:

# 克隆模板仓库

git clone https://github.com/Tuya-Community/tuya-ray-materials.git

# 进入 IPC 通用模板目录

cd ./template/PublicPanelIpc

接下来:

  1. 打开 IDE
  2. 导入上述 PublicPanelIpc 目录作为项目源码
  3. 将其关联到开发者平台中已创建的小程序与对应产品

接下来, 还需要您在小程序开发者平台完成模版内 IPC 标准能力的授权, 以保证模板内的云服务可以正常使用。

小程序开发者平台 => 开发设置 => 已授权云能力 需要包含 IPC 标准能力, 若无,需要您在未授权云能力的列表中进行手动授权。

上面的步骤我们已经初始化好了一个面板小程序的开发模板并且已针对 IPC 标准能力进行授权,下面我们介绍下工程目录。

├── src
│ ├── api # api目录
│ ├── app.config.ts # 自动生成配置
│ ├── app.tsx # App 根组件
│ ├── components # 组件目录
│ ├── constant # 常量目录
│ ├── context # 自定义上下文目录
│ ├── config # 配置文件目录
│ ├── devices # 智能设备模型目录
│ │ ├── index.ts # 定义并导出智能设备模型
│ │ └── schema.ts # 当前智能设备 DP 功能点描述,IDE 可自动生成
│ ├── entities # 功能模块ts定义
│ ├── features # 功能模块逻辑定义
│ ├── hooks # 自定义 hooks 目录
│ ├── i18n # 多语言目录
│ ├── pages # 页面目录
│ ├── redux # 状态管理
│ ├── res # 图片及资源目录
│ │ ├── iconfont # 内置图标 Icon
│ │ ├── image # 定义并导出智能设备模型
│ │ └── index 
│ ├── styles # 全局样式文件
│ ├── types # 自定义类型定义文件
│ ├── utils # 工具库
│ ├── global.config.ts
│ └── routes.config.ts # 路由配置
│─── typings #业务类型定义目录
│ └── sdm.d.ts #智能设备类型定义文件

1. 区域:

2. App 版本:

3. Kit 依赖:

4. 组件依赖:

本节主要介绍模板中如何使用融合播放器组件,实现视频展示区域。

示例代码

import { useEffect } from 'react';
import { useCtx, Features, IPCPlayerIntegration } from '@ray-js/ipc-player-integration';

const Home = props => {

  // 通过 useCtx 获取播放器实例关联上下文信息

  const instance = useCtx({
      devId: props.location.query.deviceId, // 设备ID
  });

  // 初始化融合播放器内置功能, 若不调用此事件,内置控件则不展示

  useEffect(() => {
    Features.initPlayerWidgets(instance, {
      verticalResolutionCustomClick: false,
      hideHorizontalMenu: false,
    });
  }, []);

  // 融合播放器组件引入

  <View className={Styles.playerContainer}>
    <IPCPlayerIntegration
      instance={instance}  // 传入播放器实例
      devId={devInfo.devId}   // 设备ID
      onPlayStatus={onPlayStatus}  // 简化监听播放器状态 (0: 连接中 1: 预览中)
      privateState={dpState.basic_private || false}   // 是否开启隐私模式
      deviceOnline={devInfo.isOnline} // 设备在线
      brandColor={brandColor}  // 品牌色
      playerFit='contain'  // 竖屏模式下,播放器填充模式 可选值:contain | cover
      landscapeMode="standard"  // 横屏模式下,播放器填充模式: standard | fill
      extend={{
        ptzControllable: true  // 是否开启播放器云台控制
      }}
    />
  </View>
}

export default Home;

样式设置

  .playerContainer {
     width: 100%;
     height: calc(100vw * 9 / 16);
  }

本节主要介绍模板中实现运营推广区域,实现运营推广Banner。

内置数据

模板内置运营推广数据以当前对应 APP 运营配置为准,获取方式如下:

注意: 若未展示图示框选区域, 首先判断第 5 步, IPC标准能力是否在小程序开发者平台进行授权,若授权无误,则表示当前 App 没有进行运营配置,若需相关配置,可联系 App 运营人员。

import { getVasServiceConfigList } from '@ray-js/ray';

type GetServiceHallSettingParams = {
  type: 0; // 固定值
  instanceId: string; // 设备 uuid
  homeId: string; // 家庭 ID
};

export function getServiceHallSetting(params: GetServiceHallSettingParams) {
  return getVasServiceConfigList(params);
}

自定义数据

同时您也可根据产品形态需要,自定义传入数据使用半屏组件或自行开发

import { useState } from 'react';
import HalfHorizontalDrag from '@ray-js/ray-ipc-half-horizontal-drag';

const Vas = props => {

  const goTo = (data) => {
	 console.log(data, 'data')
  }

  // 运营区域 Demo 数据

  const bannerData = [
	  {
		title: '标题1',
		icon: <Image src={iconUrl} style={{ width: '40rpx', height: '40rpx' }} />,
		tag: '标签描述',
		tagStyle: {
		  color: '#ffffff',
		  backgroundColor: '#ff0000'
		},
		style: {
			color: '#ffffff'
		},
		backgroundImage: imageUrl
		background: '#ffffff',
		onClick: () => goTo()
	  }
   ];

	return (
		<View>
			<HalfHorizontalDrag style={{ height: '110rpx', paddingLeft: '16rpx' }} data={bannerData} />
		</View>
	)

}

export default Vas;

本节主要介绍模板中重点功能区域的配置数据解析, 详情请参考以下接口定义

代码位置: components/layout-feature

配置项 FeatureMenu 接口定义

字段名

参数类型

是否必选

说明

key

string

功能标识

title

string

功能名称

icon

string

功能图标

onClick

(item) => void

点击事件

offlineAvailable

boolean

离线状态下是否可用,优先级最高

notPreviewAvailable

boolean

非播放状态下是否可用,播放状态下一定可用

isVisible

boolean

是否展示

showIcon

boolean

是否展示图标(暂无实际使用)

dpValue

boolean | string | number

DP 值

dpCode

string

DPCode 标识符

listen

boolean

是否监听 DP 变化

dpListenCallback

(value, currentItem) => void

DP 变化回调,与 listen 配合使用

hasClick

boolean

标记是否已点击,防止重复点击

type

FeatureType

功能类型,参考下方枚举

nativePage

string

原生页面路径(typenativePage 时使用)

componentKey

string

组件标识(typepopup 时使用)

miniPage

string

小程序页面路径(typeminiPage 时使用)

initDpValue

() => any

初始化 DP 值

visibilityCondition

() => Promise

异步判断是否展示,可编写逻辑

iconVisibilityCondition

() => Promise

异步判断图标是否展示(暂无实际使用)

FeatureType 枚举说明

枚举值

含义

bool

布尔型

enum

枚举型

popup

弹窗组件型

miniPage

跳转小程序使用

nativePage

跳转原生页面

本节主要介绍模板中底部快捷功能区域的配置数据解析, 详见如下

代码位置: components/feature-tab-bar

配置项 TabBar 接口定义

字段名

参数类型

是否必选

说明

key

string

功能标识

label

string

功能名称

icon

string

功能图标

onPress

(item) => void

点击事件

offlineAvailable

boolean

离线状态下是否可用,优先级最高

notPreviewAvailable

boolean

非播放状态下是否可用,播放状态下一定可用

isVisible

boolean

是否展示

showIcon

boolean

是否展示图标(暂无实际使用)

nativePage

string

原生页面路径

isCenter

boolean

是否为中心图标 (仅可有一项)

visibilityCondition

() => Promise

异步判断是否展示,可编写逻辑