扩展插件指南
扩展插件是后台服务,可以桥接外部协议、注册虚拟设备、锁定 LED 进行直接控制,并提供自定义 HTML UI 页面。
目录结构
plugins/extension.my_bridge/
├── manifest.json # 元数据 + 权限
├── init.lua # 入口脚本
├── lib/ # 可选 Lua 模块
│ └── protocol.lua
├── locales/ # 可选 i18n 文件
├── data/ # 持久化数据目录
└── page/ # 可选内嵌 HTML UI
└── dist/
└── index.html
生命周期
Core 启动 → 加载已启用的扩展
→ 初始化 Lua 环境
→ plugin.on_start() ← 扩展启动
→ [事件循环]
plugin.on_scan_devices() ← 手动扫描触发
plugin.on_devices_changed() ← 设备列表变化
plugin.on_led_locks_changed()← LED 锁状态变化
plugin.on_device_frame() ← 实时 LED 数据
plugin.on_page_message() ← 来自 HTML 页面的消息
→ plugin.on_stop() ← 扩展停止
生命周期钩子
on_start()
扩展加载时调用。在此初始化连接、启动外部进程、注册设备。
function plugin.on_start()
ext.log("扩展正在启动")
-- 连接外部服务,注册设备等
end
on_scan_devices()
用户手动触发设备扫描时调用。
function plugin.on_scan_devices()
ext.log("正在扫描设备...")
-- 发现并注册设备
end
on_devices_changed(devices)
全局设备列表变化时调用。
function plugin.on_devices_changed(devices)
-- 响应新增/移除的设备
end
on_led_locks_changed(locks)
任何 LED 锁状态变化时调用。
function plugin.on_led_locks_changed(locks)
-- locks: 当前锁定状态
end
on_device_frame(port, outputs)
每个活跃设备帧触发,携带实时 LED 颜色数据,高频(最高 30+ fps)。
function plugin.on_device_frame(port, outputs)
-- outputs: {output_id = {r,g,b,r,g,b,...}, ...}
local colors = outputs["out1"]
if colors then
-- 将颜色转发至外部系统
end
end
on_page_message(data)
内嵌 HTML 页面发送消息时调用。
function plugin.on_page_message(data)
if data.action == "refresh" then
-- 处理页面请求
ext.page_emit({status = "ok", devices = ext.get_devices()})
end
end
on_stop()
插件即将卸载时调用,清理所有资源。
function plugin.on_stop()
ext.log("扩展正在停止")
-- 关闭连接,终止进程,注销设备
end
注册虚拟设备
扩展可以注册虚拟设备,这些设备在 Skydimo 中像实体硬件一样显示:
local port = ext.register_device({
controller_port = "openrgb://device_0",
manufacturer = "Corsair",
model = "Vengeance RGB",
serial_id = "ABC123",
description = "RAM 模块",
controller_id = "extension.openrgb",
device_type = "dram",
outputs = {
{
id = "zone0",
name = "Zone 0",
leds_count = 8,
output_type = "linear",
}
}
})
这些设备从 Skydimo 接收灯效,你可以通过 on_device_frame 将渲染后的颜色转发至真实硬件。
更新设备
-- 更改设备昵称
ext.set_device_nickname(port, "我的内存条")
-- 更新输出配置
ext.update_output(port, "zone0", {
leds_count = 16,
matrix = nil -- 或 {width=4, height=4, map={...}}
})
-- 移除设备
ext.remove_extension_device(port)
LED 锁定
扩展可以锁定特定 LED 进行直接颜色控制,覆盖当前活跃的灯效:
-- 锁定 LED 0-9 进行直接控制
ext.lock_leds("COM3", "out1", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
-- 对锁定的 LED 设置颜色
ext.set_leds("COM3", "out1", {
{0, 255, 0, 0}, -- LED 0: 红
{1, 0, 255, 0}, -- LED 1: 绿
{2, 0, 0, 255}, -- LED 2: 蓝
})
-- 释放锁定
ext.unlock_leds("COM3", "out1", {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
网络(TCP)
扩展可以建立 TCP 连接。需要 "network:tcp" 权限。
-- 连接
local handle = ext.tcp_connect("127.0.0.1", 6742)
-- 带超时:
local handle = ext.tcp_connect("127.0.0.1", 6742, 5000)
-- 发送数据
local bytes_sent = ext.tcp_send(handle, data_string)
-- 接收数据
local data = ext.tcp_recv(handle, 1024) -- 最多 1024 字节
local data = ext.tcp_recv(handle, 1024, 5000) -- 带 5s 超时
local data = ext.tcp_recv_exact(handle, 256) -- 恰好 256 字节
local data = ext.tcp_recv_exact(handle, 256, 5000) -- 带超时
-- 关闭
ext.tcp_close(handle)
进程管理
扩展可以启动和管理外部进程。需要 "process" 权限。
-- 启动进程
local handle = ext.spawn_process("openrgb.exe", {"--server"}, {
hidden = true,
working_dir = ext.data_dir
})
-- 检查是否运行中
if ext.is_process_alive(handle) then
ext.log("进程正在运行")
end
-- 终止进程
ext.kill_process(handle)
灯效管理
扩展可以查询和控制设备上的灯效:
-- 获取所有可用灯效
local effects = ext.get_effects()
-- 获取灯效参数 schema
local params = ext.get_effect_params("rainbow")
-- 在设备输出端口上设置灯效
ext.set_effect("COM3", "out1", "rainbow")
ext.set_effect("COM3", "out1", "rainbow", {speed = 3.0})
页面通信
扩展可以包含一个内嵌 HTML 页面,显示在 Skydimo UI 中:
manifest.json
{
"page": "page/dist/index.html"
}
Lua 与页面之间双向通信:
-- 向 HTML 页面发送数据
ext.page_emit({type = "update", devices = ext.get_devices()})
-- 接收来自页面的消息(通过 on_page_message 钩子)
function plugin.on_page_message(data)
if data.type == "set_color" then
ext.set_leds(data.port, data.output, data.colors)
end
end
通知
向用户发送 Toast 通知:
-- 简单通知
ext.notify("连接成功", "已连接到 OpenRGB 服务器")
-- 带级别
ext.notify("警告", "设备无响应", "warn") -- "info", "warn", "error"
-- 持久通知(保持显示直到关闭)
ext.notify_persistent("conn_status", "正在连接...", "尝试连接到服务器")
-- 稍后关闭
ext.dismiss_persistent("conn_status")
完整示例:协议网桥
local plugin = {}
local conn = nil
local devices = {}
function plugin.on_start()
ext.log("网桥扩展正在启动")
-- 启动外部服务
local handle = ext.spawn_process("bridge-server.exe", {"--port", "9000"}, {
hidden = true
})
-- 等待服务器启动
ext.sleep(2000)
-- 连接
conn = ext.tcp_connect("127.0.0.1", 9000, 5000)
if not conn then
ext.error("连接网桥服务器失败")
return
end
-- 发现并注册设备
discover_devices()
end
function discover_devices()
ext.tcp_send(conn, "LIST_DEVICES\n")
local response = ext.tcp_recv(conn, 4096, 3000)
if not response then return end
-- 解析响应并注册每个设备
for name, leds in response:gmatch("(%S+):(%d+)") do
local port = ext.register_device({
controller_port = "bridge://" .. name,
manufacturer = "Bridge",
model = name,
controller_id = "extension.my_bridge",
device_type = "light",
outputs = {{
id = "main",
name = "Main",
leds_count = tonumber(leds),
output_type = "linear"
}}
})
devices[port] = {name = name, conn = conn}
end
end
function plugin.on_device_frame(port, outputs)
local dev = devices[port]
if not dev then return end
local colors = outputs["main"]
if colors then
local packet = "SET_LEDS:" .. dev.name .. ":" .. table.concat(colors, ",")
ext.tcp_send(conn, packet .. "\n")
end
end
function plugin.on_scan_devices()
discover_devices()
end
function plugin.on_stop()
-- 注销所有设备
for port in pairs(devices) do
ext.remove_extension_device(port)
end
-- 关闭连接
if conn then ext.tcp_close(conn) end
end
return plugin
完整 API 请参阅扩展 API 参考。