跳到主要内容

扩展插件指南

扩展插件是后台服务,可以桥接外部协议、注册虚拟设备、锁定 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 参考