[OpenVela] 音乐播放器1.0
基于 OpenVela 系统的嵌入式音乐播放器,使用 LVGL 图形库开发,支持 Wi-Fi 连接和本地音频播放。
·
code: https://github.com/lvy010/vela/tree/main/music_player
OpenVela 音乐播放器
基于 OpenVela 系统的嵌入式音乐播放器,使用 LVGL 图形库开发,支持 Wi-Fi 连接和本地音频播放。
📋 目录
🎵 项目简介
本项目是一个功能完整的嵌入式音乐播放器,专为 OpenVela 系统设计。它提供了现代化的用户界面,支持音频播放、播放列表管理、音量控制等功能。应用程序采用模块化设计,易于扩展和维护。
主要亮点
- 🎨 现代化 UI:基于 LVGL 的精美图形界面
- 🎵 音频支持:支持 WAV 格式音频文件播放
- 📱 触屏友好:完整的触屏操作支持
- 🌐 网络功能:内置 Wi-Fi 连接管理
- ⚡ 高性能:优化的嵌入式系统性能
- 🔧 易于扩展:模块化架构设计
✨ 功能特性
核心功能
- ▶️ 音频播放控制(播放/暂停/停止)
- ⏭️ 上一首/下一首切换
- 🔊 音量调节
- 📋 播放列表管理
- 🕒 播放进度显示
- 📊 实时时间显示
界面功能
- 📱 1280x800 分辨率支持
- 🎨 专辑封面显示
- 🎭 动态主题色彩
- 📜 滚动播放列表
- 🎛️ 可视化音量条
系统功能
- 🌐 Wi-Fi 网络连接
- 📁 文件系统集成
- 🔧 配置文件管理
- 📊 系统资源监控
🔧 系统要求
硬件要求
- 处理器:ARM Cortex-A7 或更高
- 内存:至少 128MB RAM
- 存储:至少 256MB 闪存
- 显示:1280x800 分辨率触摸屏
- 音频:PCM 音频输出支持
软件要求
- 操作系统:OpenVela
- 图形库:LVGL 8.x
- 音频库:NuttX Audio 框架
- 网络:Wi-Fi 驱动支持
开发环境
- 编译器:arm-none-eabi-gcc
- 构建系统:Make
- 调试工具:ADB
- 主机系统:Linux (推荐 Ubuntu 22.04)
📁 项目结构
music_player/
├── src/ # 源代码目录
│ ├── music_player.c # 主应用逻辑
│ ├── music_player.h # 主应用头文件
│ ├── music_player_main.c # 应用程序入口
│ ├── audio_ctl.c # 音频控制模块
│ ├── audio_ctl.h # 音频控制头文件
│ ├── wifi.c # Wi-Fi 管理模块
│ └── wifi.h # Wi-Fi 管理头文件
├── res/ # 资源文件目录
│ ├── fonts/ # 字体文件
│ │ ├── MiSans-Normal.ttf # 常规字体
│ │ └── MiSans-Semibold.ttf # 半粗体字体
│ ├── icons/ # 图标文件
│ │ ├── album_picture.png # 专辑图片
│ │ ├── audio.png # 音频图标
│ │ ├── music.png # 音乐图标
│ │ ├── mute.png # 静音图标
│ │ ├── next.png # 下一首图标
│ │ ├── nocover.png # 无封面占位图
│ │ ├── pause.png # 暂停图标
│ │ ├── play.png # 播放图标
│ │ ├── playlist.png # 播放列表图标
│ │ └── previous.png # 上一首图标
│ ├── musics/ # 音乐文件目录
│ │ ├── manifest.json # 音乐列表配置
│ │ ├── UnamedRhythm.wav # 示例音频文件
│ │ └── UnamedRhythm.png # 示例专辑封面
│ └── config.json # 全局配置文件
├── build/ # 构建输出目录
│ ├── *.o # 目标文件
│ ├── .built # 构建标记
│ └── .depend # 依赖文件
├── Kconfig # 内核配置
├── Makefile # 主构建文件
├── Make.defs # 构建定义
├── Make.dep # 构建依赖
└── README.md # 项目文档
核心模块说明
1. music_player.c/h
- 功能:应用程序主逻辑
- 职责:UI 管理、状态控制、事件处理
- 关键结构:
struct ctx_s
:运行时上下文struct resource_s
:UI 资源管理album_info_t
:专辑信息结构
2. audio_ctl.c/h
- 功能:音频控制模块
- 职责:音频播放、暂停、停止、音量控制
- 支持格式:WAV 音频文件
- 接口:NuttX Audio 框架
3. wifi.c/h
- 功能:Wi-Fi 连接管理
- 职责:网络连接、配置管理
- 配置:基于 config.json
4. 资源文件管理
- 字体:多种字重的 MiSans 字体
- 图标:SVG 转换的 PNG 图标
- 音频:WAV 格式音乐文件
- 配置:JSON 格式配置文件
🚀 快速开始
1. 环境准备
# 安装必要的工具
sudo apt update
sudo apt install -y android-tools-adb build-essential git
# 克隆 OpenVela 仓库
git clone <openvela-repo-url>
cd vela_code
2. 配置项目
# 进入项目根目录
cd /root/vela_code
# 配置音乐播放器
./build.sh vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap menuconfig
# 或者直接编辑配置文件
echo "CONFIG_LVX_USE_DEMO_MUSIC_PLAYER=y" >> vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap/defconfig
echo 'CONFIG_LVX_MUSIC_PLAYER_DATA_ROOT="/data"' >> vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap/defconfig
3. 编译项目
# 清理构建产物
./build.sh vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap distclean -j8
# 开始构建
./build.sh vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap -j8
4. 启动模拟器
# 创建 nuttx 符号链接(如果不存在)
cd nuttx && ln -sf vela_ap.elf nuttx && cd ..
# 启动模拟器
./emulator.sh vela
5. 部署资源
# 等待模拟器启动
sleep 15
# 连接 ADB
adb connect 127.0.0.1:5555
# 推送资源文件
adb -s emulator-5554 push apps/packages/demos/music_player/res /data/
6. 运行应用
# 通过 ADB Shell 启动音乐播放器
adb -s emulator-5554 shell "music_player &"
⚙️ 配置说明
config.json 配置
{
"wifi": {
"ssid": "your_wifi_name", // Wi-Fi 网络名称
"pswd": "your_password" // Wi-Fi 密码
}
}
注意:请勿在代码中硬编码敏感信息,建议通过环境变量或安全存储方式加载。
manifest.json 音乐配置
{
"musics": [
{
"path": "UnamedRhythm.wav", // 音频文件路径
"name": "UnamedRhythm", // 歌曲名称
"artist": "Benign X", // 艺术家
"cover": "UnamedRhythm.png", // 专辑封面
"total_time": 12000, // 总时长(毫秒)
"color": "#114514" // 主题颜色
}
]
}
Kconfig 配置选项
CONFIG_LVX_USE_DEMO_MUSIC_PLAYER # 启用音乐播放器
CONFIG_LVX_MUSIC_PLAYER_DATA_ROOT # 数据根目录路径
CONFIG_LVX_MUSIC_PLAYER_STACKSIZE # 应用栈大小
CONFIG_LVX_MUSIC_PLAYER_PRIORITY # 应用优先级
🔨 构建指南
构建系统概述
项目使用 NuttX 构建系统,包含以下关键文件:
Makefile
include $(APPDIR)/Make.defs
ifeq ($(CONFIG_LVX_USE_DEMO_MUSIC_PLAYER), y)
PROGNAME = music_player # 程序名称
PRIORITY = 100 # 优先级
STACKSIZE = 40960 # 栈大小(字节)
MODULE = $(CONFIG_LVX_USE_DEMO_MUSIC_PLAYER)
CSRCS = music_player.c audio_ctl.c wifi.c # C源文件
MAINSRC = music_player_main.c # 主入口文件
endif
include $(APPDIR)/Application.mk
Make.defs
ifneq ($(CONFIG_LVX_USE_DEMO_MUSIC_PLAYER),)
CONFIGURED_APPS += $(APPDIR)/packages/demos/music_player
endif
构建选项
调试版本
# 启用调试符号
./build.sh vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap DEBUG=1 -j8
发布版本
# 优化构建
./build.sh vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap OPTIMIZE=2 -j8
清理构建
# 完全清理
./build.sh vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap distclean
# 仅清理音乐播放器
make -C apps/packages/demos/music_player clean
构建产物
成功构建后会生成:
nuttx/vela_ap.elf
:主可执行文件nuttx/vela_ap.bin
:二进制映像nuttx/vela_system.bin
:系统映像nuttx/vela_data.bin
:数据映像
🚢 部署运行
模拟器部署
1. 启动模拟器
# 启动 QEMU 模拟器
./emulator.sh vela
# 检查模拟器状态
ps aux | grep qemu
2. ADB 连接
# 检查 ADB 服务
adb devices
# 连接到模拟器
adb connect 127.0.0.1:5555
# 验证连接
adb -s emulator-5554 shell uname -a
3. 文件传输
# 创建目标目录
adb -s emulator-5554 shell mkdir -p /data/res
# 推送资源文件
adb -s emulator-5554 push res/ /data/
# 验证文件
adb -s emulator-5554 shell ls -la /data/res/
硬件设备部署
1. 串口连接
# 配置串口连接
minicom -s
# 设置:115200 8N1,无流控
# 或使用 screen
screen /dev/ttyUSB0 115200
2. 网络部署
# 配置网络启动
setenv serverip 192.168.1.100
setenv ipaddr 192.168.1.200
tftp 0x40000000 vela_ap.bin
go 0x40000000
3. 存储部署
# 烧录到 Flash
flash erase 0x00000000 0x00800000
flash write 0x40000000 0x00000000 0x00800000
运行时监控
1. 系统监控
# 检查系统状态
adb shell ps
adb shell free
adb shell df -h
# 查看日志
adb shell dmesg
adb logcat
2. 应用监控
# 检查音乐播放器进程
adb shell ps | grep music_player
# 查看应用日志
adb shell tail -f /var/log/music_player.log
3. 性能分析
# CPU 使用率
adb shell top -p $(adb shell pidof music_player)
# 内存使用
adb shell cat /proc/$(adb shell pidof music_player)/status
🎨 自定义指南
添加新音乐
1. 准备音频文件
# 转换音频格式(如果需要)
ffmpeg -i input.mp3 -acodec pcm_s16le -ar 44100 -ac 2 output.wav
# 准备专辑封面(推荐 300x300)
convert cover.jpg -resize 300x300 cover.png
2. 更新配置文件
{
"musics": [
{
"path": "new_song.wav",
"name": "新歌名称",
"artist": "艺术家名称",
"cover": "new_cover.png",
"total_time": 240000,
"color": "#FF5722"
}
]
}
3. 部署文件
# 复制文件到资源目录
cp new_song.wav res/musics/
cp new_cover.png res/musics/
# 推送到设备
adb push res/musics/ /data/res/musics/
自定义界面
1. 修改主题颜色
// 在 music_player.c 中修改
#define THEME_PRIMARY_COLOR lv_color_hex(0x2196F3)
#define THEME_SECONDARY_COLOR lv_color_hex(0xFF5722)
#define THEME_BACKGROUND_COLOR lv_color_hex(0x121212)
2. 调整界面布局
// 修改分辨率适配
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 800
#define UI_SCALE_FACTOR 1.0f
// 调整控件大小
#define ALBUM_COVER_SIZE 300
#define BUTTON_SIZE 60
#define PROGRESS_BAR_HEIGHT 8
3. 添加新功能
// 添加均衡器功能
typedef struct {
int8_t bass;
int8_t middle;
int8_t treble;
} equalizer_t;
static void app_equalizer_apply(equalizer_t* eq) {
// 实现均衡器逻辑
}
扩展音频格式
1. 添加 MP3 支持
// 在 audio_ctl.c 中添加
#ifdef CONFIG_AUDIO_MP3_SUPPORT
#include <mad.h>
static int mp3_decode(const char* file_path) {
// 实现 MP3 解码
}
#endif
2. 配置构建系统
config MUSIC_PLAYER_MP3_SUPPORT
bool "Enable MP3 support"
default n
depends on LVX_USE_DEMO_MUSIC_PLAYER
🔧 故障排除
常见问题
1. 编译错误
问题:music_player: command not found
# 解决方案:检查配置
grep -r LVX_USE_DEMO_MUSIC_PLAYER vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap/defconfig
# 重新配置和编译
./build.sh vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap distclean
./build.sh vendor/openvela/boards/vela/configs/goldfish-armeabi-v7a-ap -j8
问题:栈溢出错误
# 解决方案:增加栈大小
# 编辑 Makefile
STACKSIZE = 65536 # 从 32768 增加到 65536
2. 运行时错误
问题:找不到资源文件
# 检查文件是否存在
adb shell ls -la /data/res/
# 重新推送资源
adb push res/ /data/
问题:音频播放失败
# 检查音频设备
adb shell ls -la /dev/audio/
# 检查音频格式
file res/musics/*.wav
3. 模拟器问题
问题:模拟器启动失败
# 检查 nuttx 文件
ls -la nuttx/nuttx
# 重新创建符号链接
cd nuttx && rm -f nuttx && ln -sf vela_ap.elf nuttx
问题:ADB 连接失败
# 检查端口
netstat -tlnp | grep 555
# 重新连接
adb disconnect 127.0.0.1:5555
adb connect 127.0.0.1:5555
调试技巧
1. 使用日志输出
// 添加调试日志
#define MUSIC_DEBUG 1
#if MUSIC_DEBUG
#define DLOG(fmt, ...) printf("[MUSIC] " fmt "\n", ##__VA_ARGS__)
#else
#define DLOG(fmt, ...)
#endif
// 在关键位置添加日志
DLOG("Loading audio file: %s", file_path);
DLOG("Audio playback started, duration: %lu ms", duration);
2. 使用 GDB 调试
# 启动 GDB 服务器
./emulator.sh vela -s -S
# 连接 GDB
arm-none-eabi-gdb nuttx/nuttx
(gdb) target remote localhost:1234
(gdb) b main
(gdb) c
3. 内存分析
// 添加内存使用统计
static void print_memory_usage(void) {
struct mallinfo info = mallinfo();
printf("Memory usage:\n");
printf(" Total heap: %d bytes\n", info.arena);
printf(" Used heap: %d bytes\n", info.uordblks);
printf(" Free heap: %d bytes\n", info.fordblks);
}
性能优化
1. 界面优化
// 减少不必要的重绘
lv_obj_add_flag(obj, LV_OBJ_FLAG_FLOATING);
// 使用缓存提高性能
lv_obj_set_style_bg_opa(obj, LV_OPA_COVER, 0);
2. 音频优化
// 优化音频缓冲区大小
#define AUDIO_BUFFER_SIZE (4096 * 4) // 16KB 缓冲区
// 使用DMA传输
static int audio_dma_setup(void) {
// 配置 DMA 音频传输
}
3. 内存优化
// 预分配内存池
static uint8_t audio_buffer_pool[AUDIO_BUFFER_SIZE * 4];
static uint8_t ui_buffer_pool[UI_BUFFER_SIZE];
// 使用对象池管理
static album_info_t album_pool[MAX_ALBUMS];
🏗️ 技术架构
架构概览
数据流图
模块关系
关键数据结构
运行时上下文
struct ctx_s {
bool resource_healthy_check; // 资源健康检查
album_info_t* current_album; // 当前专辑
lv_obj_t* current_album_related_obj; // 关联UI对象
uint16_t volume; // 音量
play_status_t play_status_prev; // 上一次播放状态
play_status_t play_status; // 当前播放状态
uint64_t current_time; // 当前播放时间
struct {
lv_timer_t* volume_bar_countdown; // 音量条倒计时
lv_timer_t* playback_progress_update; // 播放进度更新
} timers;
audioctl_s* audioctl; // 音频控制句柄
};
资源管理
struct resource_s {
struct {
lv_obj_t* time; // 时间显示
lv_obj_t* date; // 日期显示
lv_obj_t* player_group; // 播放器组
// ... 更多UI组件
} ui;
struct {
struct { lv_font_t* normal; } size_16;
struct { lv_font_t* bold; } size_22;
// ... 更多字体
} fonts;
struct {
lv_style_t button_default; // 按钮默认样式
lv_style_t button_pressed; // 按钮按下样式
// ... 更多样式
} styles;
album_info_t* albums; // 专辑数组
uint8_t album_count; // 专辑数量
};
状态机设计
typedef enum {
PLAY_STATUS_STOP, // 停止
PLAY_STATUS_PLAY, // 播放
PLAY_STATUS_PAUSE, // 暂停
} play_status_t;
// 状态转换表
static const state_transition_t transitions[] = {
{PLAY_STATUS_STOP, PLAY_STATUS_PLAY, action_start_playback},
{PLAY_STATUS_PLAY, PLAY_STATUS_PAUSE, action_pause_playback},
{PLAY_STATUS_PAUSE, PLAY_STATUS_PLAY, action_resume_playback},
{PLAY_STATUS_PLAY, PLAY_STATUS_STOP, action_stop_playback},
{PLAY_STATUS_PAUSE, PLAY_STATUS_STOP, action_stop_playback},
};
📚 API 参考
核心 API
应用程序控制
/**
* @brief 创建并初始化音乐播放器应用
* @return void
*/
void app_create(void);
/**
* @brief 设置播放状态
* @param status 播放状态
*/
static void app_set_play_status(play_status_t status);
/**
* @brief 切换到指定专辑
* @param index 专辑索引
*/
static void app_switch_to_album(int index);
/**
* @brief 设置音量
* @param volume 音量值 (0-100)
*/
static void app_set_volume(uint16_t volume);
音频控制 API
/**
* @brief 初始化音频控制器
* @param file_path 音频文件路径
* @return 音频控制句柄
*/
audioctl_s* audio_ctl_init_nxaudio(const char* file_path);
/**
* @brief 开始播放
* @param audioctl 音频控制句柄
* @return 0 成功, -1 失败
*/
int audio_ctl_start(audioctl_s* audioctl);
/**
* @brief 暂停播放
* @param audioctl 音频控制句柄
* @return 0 成功, -1 失败
*/
int audio_ctl_pause(audioctl_s* audioctl);
/**
* @brief 停止播放
* @param audioctl 音频控制句柄
* @return 0 成功, -1 失败
*/
int audio_ctl_stop(audioctl_s* audioctl);
/**
* @brief 设置音量
* @param audioctl 音频控制句柄
* @param volume 音量值
* @return 0 成功, -1 失败
*/
int audio_ctl_set_volume(audioctl_s* audioctl, uint16_t volume);
Wi-Fi 管理 API
/**
* @brief Wi-Fi 配置结构
*/
typedef struct {
char ssid[64]; // 网络名称
char psk[128]; // 密码
uint32_t conn_delay; // 连接延迟
} wifi_conf_t;
/**
* @brief 连接 Wi-Fi
* @param conf Wi-Fi 配置
* @return 0 成功, -1 失败
*/
int wifi_connect(wifi_conf_t* conf);
/**
* @brief 断开 Wi-Fi 连接
* @return 0 成功, -1 失败
*/
int wifi_disconnect(void);
/**
* @brief 获取连接状态
* @return true 已连接, false 未连接
*/
bool wifi_is_connected(void);
UI 组件 API
事件处理
/**
* @brief 播放按钮事件处理
* @param e 事件对象
*/
static void app_play_status_event_handler(lv_event_t* e);
/**
* @brief 音量条事件处理
* @param e 事件对象
*/
static void app_volume_bar_event_handler(lv_event_t* e);
/**
* @brief 播放列表事件处理
* @param e 事件对象
*/
static void app_playlist_event_handler(lv_event_t* e);
UI 刷新
/**
* @brief 刷新专辑信息显示
*/
static void app_refresh_album_info(void);
/**
* @brief 刷新播放进度
*/
static void app_refresh_playback_progress(void);
/**
* @brief 刷新音量条
*/
static void app_refresh_volume_bar(void);
/**
* @brief 刷新播放列表
*/
static void app_refresh_playlist(void);
配置 API
配置文件管理
/**
* @brief 读取配置文件
*/
static void read_configs(void);
/**
* @brief 重新加载音乐配置
*/
static void reload_music_config(void);
/**
* @brief 保存配置
* @param config 配置结构
* @return 0 成功, -1 失败
*/
int save_config(const config_t* config);
资源管理
/**
* @brief 初始化资源
* @return true 成功, false 失败
*/
static bool init_resource(void);
/**
* @brief 加载字体资源
* @return true 成功, false 失败
*/
static bool load_fonts(void);
/**
* @brief 加载图片资源
* @return true 成功, false 失败
*/
static bool load_images(void);
/**
* @brief 释放资源
*/
static void cleanup_resources(void);
错误代码
#define MUSIC_ERROR_OK 0 // 成功
#define MUSIC_ERROR_INVALID_PARAM -1 // 无效参数
#define MUSIC_ERROR_NO_MEMORY -2 // 内存不足
#define MUSIC_ERROR_FILE_NOT_FOUND -3 // 文件未找到
#define MUSIC_ERROR_AUDIO_INIT -4 // 音频初始化失败
#define MUSIC_ERROR_NETWORK -5 // 网络错误
#define MUSIC_ERROR_CONFIG -6 // 配置错误
🤝 贡献指南
开发流程
-
Fork 项目
git clone https://github.com/your-username/openvela-music-player.git cd openvela-music-player
-
创建功能分支
git checkout -b feature/new-feature
-
开发和测试
# 开发新功能 # 编写测试用例 # 运行测试 make test
-
提交更改
git add . git commit -m "feat: add new audio format support"
-
推送和PR
git push origin feature/new-feature # 创建 Pull Request
代码规范
C 代码风格
// 函数命名:snake_case
static void app_create_main_page(void);
// 变量命名:snake_case
static bool resource_healthy_check = false;
// 常量命名:UPPER_CASE
#define MAX_ALBUM_COUNT 100
// 结构体命名:snake_case_t
typedef struct album_info_s {
const char* name;
const char* artist;
} album_info_t;
注释规范
/**
* @brief 函数简要描述
* @param param1 参数1描述
* @param param2 参数2描述
* @return 返回值描述
* @note 注意事项
* @warning 警告信息
*/
int function_name(int param1, const char* param2);
提交信息规范
feat: 新功能
fix: 修复bug
docs: 文档更新
style: 代码格式调整
refactor: 重构
test: 测试相关
chore: 构建/工具相关
示例:
feat: add MP3 audio format support
fix: resolve memory leak in audio playback
docs: update API documentation
测试指南
单元测试
// test/test_audio_ctl.c
#include "unity.h"
#include "audio_ctl.h"
void test_audio_ctl_init(void) {
audioctl_s* ctl = audio_ctl_init_nxaudio("test.wav");
TEST_ASSERT_NOT_NULL(ctl);
audio_ctl_uninit_nxaudio(ctl);
}
void test_audio_ctl_volume(void) {
audioctl_s* ctl = audio_ctl_init_nxaudio("test.wav");
int result = audio_ctl_set_volume(ctl, 50);
TEST_ASSERT_EQUAL(0, result);
audio_ctl_uninit_nxaudio(ctl);
}
集成测试
# 运行完整测试套件
./scripts/run_tests.sh
# 运行性能测试
./scripts/performance_test.sh
# 运行内存泄漏测试
valgrind --leak-check=full ./music_player
文档贡献
- API 文档:使用 Doxygen 格式
- 用户文档:使用 Markdown 格式
- 代码示例:提供完整可运行的示例
- 翻译:支持多语言文档
问题报告
提交 Issue 时请包含:
- 操作系统和版本
- OpenVela 版本
- 复现步骤
- 期望行为
- 实际行为
- 相关日志
📄 许可证
本项目采用 Apache License 2.0 开源许可证。详情请参阅 LICENSE 文件。
🙏 致谢
- OpenVela 团队:提供优秀的嵌入式操作系统
- LVGL 社区:提供强大的图形库
- NuttX 项目:提供可靠的实时操作系统内核
📞 联系
- 项目主页:https://github.com/openvela/music-player
- 文档站点:https://docs.openvela.org/music-player
- 问题反馈:https://github.com/openvela/music-player/issues
- 讨论社区:https://forum.openvela.org
最后更新时间:2024-08-24

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)