# zaiohController_ct16_second_develop **Repository Path**: zaihong/zaiohController_ct16_second_develop ## Basic Information - **Project Name**: zaiohController_ct16_second_develop - **Description**: 在鸿控制器CT16应用与设备模型开发 SDK,面向客户二次开发场景,提供应用程序、设备模型及通信协议适配所需的开发接口、示例工程、构建工具和配套文档,支持编译生成可在 OpenHarmony 设备上部署运行的二进制应用和设备模型动态库。 - **Primary Language**: C - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-16 - **Last Updated**: 2026-09-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # CT16 二次开发 SDK 使用指南 本文档面向第一次接触 CT16 二次开发 SDK 的开发人员,按实际操作顺序说明以下工作: 1. 编译并运行随 SDK 提供的 `example` 应用。 2. 新建自己的业务应用并生成 `.ohcp` 工程包。 3. 创建 DSDK 设备模型、编写协议逻辑并生成模型插件 `.so`。 4. 在 CT16 设备管理平台导入应用、设备模型和设备实例。 5. 获取系统 OTA 固件并通过设备管理平台完成升级。 所有命令默认都在 SDK 根目录执行,也就是当前 `README.md` 所在目录。 ## 1. 先认识三类文件 CT16 开发涉及三类用途完全不同的交付文件: | 文件 | 示例 | 用途 | 生成或获取方式 | | --- | --- | --- | --- | | OTA 固件 | `ct16_YYYYMMDD_ota.img` | 升级 CT16 整机系统 | 完整 OpenHarmony 主工程编译生成,或由设备提供方交付 | | 应用工程包 | `example.ohcp` | 安装或升级业务应用 | 在本 SDK 中执行 `./build.sh ` | | 设备模型插件 | `libplugin_*.so` | 描述并驱动南向设备 | 编辑设备模型后执行 `./build.sh ` | 不要把 `.ohcp` 上传到 OTA 页面,也不要把 OTA `.img` 上传到应用管理页面。 ## 2. 开发环境要求 SDK 已包含交叉编译工具链、GN、Ninja 和目标板 `sysroot`,不需要单独安装 OpenHarmony SDK。 开发主机需要满足以下条件: - 使用 x86_64 Linux 系统。 - 能执行 Bash 脚本。 - 已安装 Python 3。 - SDK 所在目录具有读写权限。 - SDK 路径及其父目录尽量不要包含空格或特殊字符。 - 用于访问 CT16 Web 管理平台的电脑与设备网络互通。 确认基础命令可用: ```bash bash --version python3 --version ``` 不要修改或移动 `prebuilts/`、`sysroot/`、`tools/`。首次编译时,`build.sh` 会自动在当前 SDK 中初始化编译环境。 ## 3. SDK 目录说明 ```text . ├── application/ # 示例应用和自建业务应用 ├── components/ # SDK 对外开放的头文件和库 ├── docs/images/ # 本文档使用的操作截图 ├── dsdk_model/ │ ├── docs/ # 设备模型 Markdown 文档 │ ├── gennerator/ # 设备模型网页编辑器和代码生成器 │ ├── skill/ # 设备模型自然语言生成 Skill │ └── src/ # 设备模型 C 源码及插件清单 ├── prebuilts/ # Clang、GN、Ninja 等预编译工具 ├── sysroot/ # CT16 目标系统头文件和库 ├── tools/ # 环境初始化、打包和 GN 辅助脚本 ├── build.sh # 应用及设备模型统一构建入口 ├── start_model_develop # 启动设备模型网页编辑器 └── README.md # 当前使用指南 ``` 编译后还会出现以下本地目录和文件: ```text .sdk/ # 当前 SDK 的编译器包装脚本 env.sh # 当前 SDK 的环境变量 out/apps// # 应用编译中间产物和可执行文件 out/.ohcp # 最终业务应用工程包 out/libplugin_.so # 设备模型集合插件 out/plugins/libplugin_*.so # 单设备模型插件 ``` 这些内容都和当前 SDK 路径绑定。移动 SDK 后,直接重新执行构建命令,脚本会检测并重新初始化环境。 ## 4. 五分钟跑通 example ### 4.1 编译示例应用 进入 SDK 根目录执行: ```bash ./build.sh example ``` 第一次执行会自动完成以下工作: 1. 检查并初始化工具链环境。 2. 根据设备模型清单生成模型插件构建文件。 3. 编译 `application/example/BUILD.gn` 中的全部示例进程。 4. 编译设备模型集合插件和单模型插件。 5. 把应用整理成 `out/example.ohcp`。 编译完成后重点检查: ```text out/example.ohcp out/apps/example/bin/ out/libplugin_environment.so out/plugins/libplugin_*.so ``` ![编译 example 及查看输出文件](docs/images/app-build-output.png) 如果只修改了打包配置,希望使用已有编译产物重新打包,可以执行: ```bash ./tools/pack_app.sh example ``` ### 4.2 导入 example.ohcp 浏览器登录 CT16 设备管理平台,打开“应用管理”,点击右上角“应用导入”,选择: ```text out/example.ohcp ``` ![在应用管理页面导入 OHCP 工程包](docs/images/app-import.png) 同名应用再次导入会执行升级。导入前不要修改 `.ohcp` 的内部文件,也不要把其他压缩格式直接改成 `.ohcp` 后缀。 ### 4.3 启动、停止和配置进程 导入成功后,应用管理页面会显示应用中的全部进程。每个进程的名称、入口、自动启动、异常重启、启动延时和依赖关系来自: ```text application/example/manifest.json ``` 进程卡片右下角的开关用于启动或停止进程;右上角的参数按钮用于调整进程启动策略。 ![查看进程状态并修改启动参数](docs/images/app-process-settings.png) 保存进程参数前,需要先停止整个应用。参数含义如下: | 参数 | 含义 | | --- | --- | | `autoStart` | 设备上电或应用启用后是否自动拉起进程 | | `restart` | 进程意外退出后是否自动重新拉起 | | `delayMs` | 所有依赖满足后额外等待的毫秒数 | | `dependsOn` | 当前进程启动前必须先运行的其他进程 | 通过设备终端也可以控制单个进程: ```bash app_ctl status app_ctl start app_ctl stop ``` ## 5. 理解应用的目录和命名规则 ### 5.1 build.sh 如何找到应用 `./build.sh example` 中的 `example` 直接对应 `application/` 下的一级目录: ```text ./build.sh example ↓ application/example/ ↓ application/example/BUILD.gn ↓ group("example_group") ↓ //application/example:example_group ``` 两个强制约定是: 1. 命令参数必须等于应用一级目录名。 2. `BUILD.gn` 必须提供 `group("<目录名>_group")`。 ![应用名称和 GN group 的对应关系](docs/images/app-naming-rules.png) 其他名称的职责如下: | 名称 | 定义位置 | 作用 | | --- | --- | --- | | `example` | `application/example/` | `build.sh` 的应用选择参数 | | `example_group` | `BUILD.gn` | 当前应用的统一构建入口 | | `example_hilog` | `executable()` | 实际生成的可执行文件名 | | `"name": "example"` | `manifest.json` | 安装到设备后的应用名称 | | `bin/example_hilog` | `processes[].entry` | 工程包内的进程入口 | ### 5.2 BUILD.gn 决定编译什么 每个 `executable()` 定义一个可执行文件,`sources` 指定源码,`deps` 指定 SDK 组件依赖: ```gn executable("example_params_manage") { sources = [ "src/example_params_manage.c" ] deps = [ "//components/hilog:hilog", "//components/params_manage:params_manage", ] output_dir = "$root_out_dir/bin" } ``` ![源码、executable 和组件依赖的关系](docs/images/app-build-target.png) 所有需要随应用构建的目标都必须加入应用 group: ```gn group("example_group") { deps = [ ":example_hilog", ":example_params_manage", ] } ``` ### 5.3 manifest.json 决定设备如何运行 `manifest.json` 不负责选择源码,它描述应用包和进程运行方式: ```json { "name": "example", "version": "1.0.0", "processes": [ { "name": "example_params_manage", "entry": "bin/example_params_manage", "autoStart": false, "restart": false, "delayMs": 1000, "dependsOn": [ "example_hilog" ] } ] } ``` ![源码文件和 manifest 进程入口的对应关系](docs/images/app-manifest-process.png) 必须保证以下三处名称能够对应: ```text BUILD.gn: executable("example_params_manage") manifest: "entry": "bin/example_params_manage" 构建结果: out/apps/example/bin/example_params_manage ``` ## 6. 新增自己的应用 下面以新建单进程应用 `demo` 为例。 ### 6.1 创建目录 在 SDK 根目录创建: ```text application/demo/ ├── src/ │ └── demo_main.c ├── BUILD.gn └── manifest.json ``` 可以复制 `application/example/` 作为参考,但要删除不需要的源码、构建目标和进程配置,避免把示例功能一起打包。 ### 6.2 编写源码 `application/demo/src/demo_main.c` 示例: ```c /* * Copyright (c) 2026 Hunan OpenValley Digital Industry Development Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #ifndef LOG_DOMAIN #define LOG_DOMAIN 0xD0028001 #endif #ifndef LOG_TAG #define LOG_TAG "demo_main" #endif #include "hiview_log.h" static volatile sig_atomic_t g_isRunning = 1; static void DemoHandleSignal(int signalCode) { (void)signalCode; g_isRunning = 0; } int main(void) { signal(SIGINT, DemoHandleSignal); signal(SIGTERM, DemoHandleSignal); while (g_isRunning) { HILOG_INFO(LOG_APP, "demo application is running"); sleep(3); } HILOG_INFO(LOG_APP, "demo application stopped"); return 0; } ``` ### 6.3 编写 BUILD.gn `application/demo/BUILD.gn`: ```gn # Copyright (c) 2026 Hunan OpenValley Digital Industry Development Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. executable("demo_main") { sources = [ "src/demo_main.c" ] deps = [ "//components/hilog:hilog" ] output_dir = "$root_out_dir/bin" } group("demo_group") { deps = [ ":demo_main" ] } ``` 可用组件及头文件说明见 `components/COMPONENTS.md`。增加组件依赖时使用: ```gn deps = [ "//components/hilog:hilog", "//components/controller_service:controller_service", ] ``` ### 6.4 编写 manifest.json `application/demo/manifest.json`: ```json { "name": "demo", "version": "1.0.0", "processes": [ { "name": "demo_main", "entry": "bin/demo_main", "autoStart": true, "restart": true } ] } ``` 应用目录名、应用 group 前缀和 `manifest.json` 的 `name` 建议保持一致。进程 `entry` 的文件名必须和 `executable()` 名称一致。 ### 6.5 编译和导入 ```bash ./build.sh demo ``` 成功后会生成: ```text out/demo.ohcp ``` 回到设备管理平台的“应用管理”,通过“应用导入”安装 `out/demo.ohcp`。 如果需要编译 `application/` 下全部一级应用目录: ```bash ./build.sh all ``` 清理单个应用或全部应用的编译产物: ```bash ./build.sh clean demo ./build.sh clean ``` 清理操作不会删除工具链、`env.sh` 或 `.sdk/`。 ## 7. 新增 DSDK 设备模型 设备模型描述设备类型、厂商、型号、通信接口、状态属性和控制属性。完整流程为: ```text 填写模型 → 生成 Markdown 和 C/H 框架 → 补充协议业务代码 → 编译模型插件 SO → Web 导入设备模型 → 创建设备实例并填写接口参数 ``` ### 7.1 启动设备模型开发服务 在 SDK 根目录执行: ```bash ./start_model_develop ``` 也可以指定其他端口: ```bash ./start_model_develop 9000 ``` 终端会输出本机访问地址和候选网络地址。开发机浏览器优先使用本机地址: ```text http://127.0.0.1:8765/ ``` ![启动设备模型开发服务](docs/images/model-server-start.png) `172.17.x.x` 等候选地址可能属于容器或虚拟网卡,只有网络路由和端口映射正确时才能访问。 ### 7.2 填写设备模型 浏览器打开模型编辑器后,按页面顺序完成: 1. “基本信息”:填写模型名称、设备类型、厂商、型号和软件版本。 2. “接口配置”:选择 RS485、RS232、TCP、UDP 或 I/O 等接口,并填写默认通信参数。 3. “模型定义”:增加状态属性和控制属性,填写数据类型、取值范围、步长和示例报文。 4. 检查右侧 Markdown 预览和页面顶部校验结果。 5. 点击“生成代码框架”。 ![设备模型编辑器](docs/images/device-model-editor.png) 生成成功后主要得到: ```text dsdk_model/docs/<设备类型>_<厂商>_<型号>.md dsdk_model/src/<设备类型>/<厂商>_<型号>.c dsdk_model/src/<设备类型>/<厂商>_<型号>.h dsdk_model/src/plugins_manifest.json ``` 已有模型可以通过“加载模型”打开。重新生成时: - `incremental`:保留 `USER CODE BEGIN/END` 中的代码并更新自动生成部分。 - `overwrite`:完全覆盖自动生成文件,只适用于确认不需要保留旧实现的情况。 ### 7.3 补充协议和硬件逻辑 生成器只创建可编译框架,不会猜测真实设备协议。必须根据设备协议手册补充以下内容: - 通信数据组帧、发送、接收和校验。 - 寄存器地址、功能码、字节序和数据换算。 - 设备初始化和异常处理。 - 状态读取和控制命令处理。 业务代码只能写在生成文件的以下区域中: ```c /* USER CODE BEGIN */ /* 在这里补充业务实现 */ /* USER CODE END */ ``` 不要修改自动生成区域或标记文本,否则增量生成会拒绝覆盖。 ### 7.4 编译设备模型插件 设备模型插件随任意应用构建一起生成,通常继续使用示例应用验证: ```bash ./build.sh example ``` 生成结果: ```text out/libplugin_.so out/plugins/libplugin__<设备类型>_<厂商>_<型号>.so ``` 其中 `out/plugins/` 下的是单模型插件,适合在 Web 页面创建单个设备模型。 ### 7.5 导入设备模型 登录设备管理平台,打开“南向设备接入”,切换到“设备模型”,点击“创建模型”。 ![进入设备模型列表并创建模型](docs/images/device-model-list.png) 在“协议驱动文件”中选择 `out/plugins/` 下对应的单模型 `.so`。 系统会从插件中读取设备类型、厂商、型号、版本和模型描述;选择图标和适用场景后确认创建。 ![选择 DSDK 协议驱动文件](docs/images/device-model-import.png) ### 7.6 创建设备实例 模型导入后,切换到“设备实例”,点击“添加设备”: 1. 填写设备名称和唯一 SN。 2. 选择刚导入的设备模型。 3. 根据模型接口填写串口、TCP、UDP 或 I/O 参数。 4. 多设备共用一条通信链路时,按模型定义填写设备地址。 5. 确认添加并检查设备状态。 ![选择模型并填写设备接口参数](docs/images/device-instance-create.png) 设备实例只保存实际接口配置值。模型名称、参数定义和物模型结构来自模型插件,不应重复写入实例配置。 ## 8. 系统 OTA 固件和升级 ### 8.1 SDK 能否编译 OTA 当前二次开发 SDK 用于构建业务应用和设备模型插件,不包含完整 OpenHarmony 系统源码,因此不能在本 SDK 根目录生成 OTA 固件。 有完整 CT16 OpenHarmony 主工程时,在主工程根目录执行: ```bash ./build.sh --product-name=ct16 --ccache --no-prebuilt-sdk ``` 构建成功后,OTA 文件位于: ```text out/ct16/ct16/image/ct16_YYYYMMDD_ota.img ``` 只有二次开发 SDK 时,应从设备提供方获取与当前 CT16 产品匹配的 OTA `.img` 文件。 ### 8.2 通过 Web 升级 1. 登录 CT16 设备管理平台。 2. 打开“OTA 升级”。 3. 拖入 OTA `.img`,或点击上传区域选择文件。 4. 等待产品标识校验、上传和升级完成。 5. 设备重启后重新登录,确认系统版本和业务功能。 ![上传 CT16 OTA 固件](docs/images/ota-upload.png) 升级前必须确认: - 固件明确适用于当前 CT16 硬件和产品标识。 - 设备供电稳定,升级过程中不掉电。 - 管理电脑与设备网络稳定。 - 已备份必要的业务配置和应用包。 升级过程中不要关闭设备电源或重复提交固件。 ## 9. 常用命令 ```bash # 编译并打包指定应用 ./build.sh example # 编译并打包 application/ 下全部一级应用 ./build.sh all # 清理指定应用输出 ./build.sh clean example # 清理全部应用输出 ./build.sh clean # 使用已有编译产物重新打包 ./tools/pack_app.sh example # 启动设备模型开发服务 ./start_model_develop # 初始化环境并加载到当前终端 source ./tools/use_env.sh ``` 日常开发通常只需要重复执行 `./build.sh `。脚本会自动判断环境是否有效。 ## 10. 常见问题 ### 10.1 提示 app directory not found 命令参数必须等于 `application/` 下的一级目录名。例如目录是 `application/demo/`,命令必须是: ```bash ./build.sh demo ``` ### 10.2 GN 提示找不到 `_group` 检查应用 `BUILD.gn` 是否包含: ```gn group("_group") { deps = [ ... ] } ``` 例如 `application/demo/` 必须定义 `group("demo_group")`。 ### 10.3 提示 binary not found after ninja build 检查 `manifest.json` 中每个 `processes[].entry` 的文件名是否与 `BUILD.gn` 中的 `executable()` 名称一致。 ### 10.4 组件头文件或库找不到 先查看 `components/COMPONENTS.md`,确认组件名称、公开头文件和使用方式,然后在应用 `BUILD.gn` 的 `deps` 中添加对应目标。 ### 10.5 设备模型编辑器只能访问 127.0.0.1 `127.0.0.1` 是本机地址,可以直接用于本机浏览器。候选网络地址可能属于容器或虚拟网卡; 跨机器访问需要正确的端口映射、路由和防火墙规则。 ### 10.6 应用导入后部分进程没有启动 检查对应进程的 `autoStart`、`dependsOn` 和 `delayMs`。`autoStart=false` 的进程需要在应用管理页面或使用 `app_ctl` 手动启动。 ### 10.7 模型导入成功但设备不能通信 依次检查: 1. 设备实例选择的模型是否正确。 2. 串口、IP、端口和设备地址是否与现场设备一致。 3. 模型源码中的协议、校验、字节序和数据换算是否按真实手册实现。 4. 设备接口是否被其他进程占用。 5. DSDK 服务日志中是否有插件加载或通信错误。 ## 11. 进一步阅读 - `application/example/README.md`:示例进程和 `manifest.json` 字段说明。 - `components/COMPONENTS.md`:SDK 开放组件总览。 - `components//README.md`:具体组件接口说明。 - `dsdk_model/gennerator/README.md`:设备模型生成模式和增量保护规则。 - `dsdk_model/src/README.md`:设备模型源码、插件清单和输出库说明。 - `dsdk_model/skill/device-model/SKILL.md`:使用 AI 编程工具生成设备模型的工作流。