对接目标
全面监测控制是最终实现目标,具体包括:
展示效果

对接思路
整体对接分为如下几个部分:
- 修路:目的是让设备和系统能够通信,确保“货物”可以互相送到。这个包括了创建设备模板,创建主题映射,配置设备的MQTT等操作
- 收货:目的是彼此来发的信息,对方能明白。主要是创建上下行脚本,翻译对方发来的信息。
对接技术细节
路是如何修通的

系统是如何工作的

对接过程
配置Wled的MQTT,让设备可以上报信息到ThingsPanel平台
首先要进入到Wled的配置界面,一般通过类似http://192.168.31.69/这样的访问地址进入到后台界面。
配置wled的MQTT部分,具体在config的Sync Interfaces里面。

这些配置参数是从ThingsPanel的设备连接中获得的,当你创建了设备,自然就看到了这些参数,然后填写到Wled配置界面中。
配置ThingsPanel的设备模板中的主题转换,全面打通上下行的信息通路

配置脚本,对上下行的信息进行编解码,确保系统和设备彼此都能听懂对方的语言。
上报脚本,添加到设备模板中的数据处理Tab中,使用预处理遥测选项。
function encodeInp(msg, topic)
local json = require("json")
local telemetryData = {}
-- 【辅助函数】正则提取并转数字,若失败返回默认值
local function extract(pattern, default)
local val = string.match(msg, pattern)
if val then return tonumber(val) else return default end
end
-- === 场景 1: 处理 WLED 标准 XML 状态 (来自 /v 主题) ===
-- 特征:包含 <vs> 或 <ac> 标签
if string.find(msg, "<") and string.find(msg, ">") then
-- 1. 基础信息
local bri = extract("<ac>(%d+)</ac>", 0)
telemetryData["brightness"] = bri
-- 推导开关状态 (亮度>0 视为开)
if bri > 0 then
telemetryData["power_state"] = 1
else
telemetryData["power_state"] = 0
end
-- 2. 颜色信息 (最重要!提取 RGB 并合成 HEX)
local r = extract("<cl>(%d+)</cl>", 0) -- cl = Color Red
local g = extract("<cs>(%d+)</cs>", 0) -- cs = Color Green (Select)
local b = extract("<cb>(%d+)</cb>", 0) -- cb = Color Blue
local w = extract("<cw>(%d+)</cw>", 0) -- cw = Color White (如果有)
telemetryData["color_r"] = r
telemetryData["color_g"] = g
telemetryData["color_b"] = b
-- 合成 HEX 颜色字符串 (例如 #FF0000),方便前端直接展示颜色块
telemetryData["color_hex"] = string.format("#%02X%02X%02X", r, g, b)
-- 3. 特效详情 (Effects)
telemetryData["effect_id"] = extract("<fx>(%d+)</fx>", 0) -- 特效ID
telemetryData["effect_speed"] = extract("<sx>(%d+)</sx>", 128) -- 速度
telemetryData["effect_intensity"] = extract("<ix>(%d+)</ix>", 128) -- 强度
-- 4. 调色板 (Palette)
telemetryData["palette_id"] = extract("<fp>(%d+)</fp>", 0)
-- 5. 其他高级信息
-- 夜灯模式 (Nightlight): 0=关, 1=开
telemetryData["nightlight_active"] = extract("<nl>(%d+)</nl>", 0)
-- 预设 ID
telemetryData["preset_id"] = extract("<pl>(%d+)</pl>", -1)
-- === 场景 2: 处理纯数字 (通常来自 /g 主题,仅亮度) ===
elseif tonumber(msg) then
local bri = tonumber(msg)
telemetryData["brightness"] = bri
telemetryData["power_state"] = (bri > 0) and 1 or 0
-- === 场景 3: 处理 HEX 颜色串 (通常来自 /c 主题) ===
-- 例如 FF0000 或 #FF0000
elseif string.match(msg, "^#?%x+$") then
local hex = msg:gsub("#", "")
if #hex == 6 then
telemetryData["color_hex"] = "#" .. hex
-- 反解 RGB
telemetryData["color_r"] = tonumber("0x" .. hex:sub(1,2))
telemetryData["color_g"] = tonumber("0x" .. hex:sub(3,4))
telemetryData["color_b"] = tonumber("0x" .. hex:sub(5,6))
end
-- === 场景 4: 尝试 JSON 解析 (容错) ===
else
local status, decoded = pcall(json.decode, msg)
if status and decoded then
-- 如果本身就是 JSON,直接尝试提取核心字段
if decoded.bri then telemetryData["brightness"] = decoded.bri end
if decoded.on ~= nil then telemetryData["power_state"] = decoded.on and 1 or 0 end
end
end
-- 如果解析出的表不为空,则返回 JSON;否则返回原始数据以便排查
if next(telemetryData) ~= nil then
return json.encode(telemetryData)
else
-- 只有在真的什么都解析不出来时,才放入 _raw,避免垃圾数据刷屏
return json.encode({ _raw = msg })
end
end
下行脚本,添加到设备模板中的数据处理Tab中,使用下发数据预处理选项。
function encodeInp(msg, topic)
local json = require("json")
-- 安全解析输入,防止空数据报错
local status, inputData = pcall(json.decode, msg)
if not status or not inputData then return msg end
local wledPayload = {}
local cmd = inputData.command
-- === 1. 开关控制 ===
if cmd == "turn_on" then
wledPayload["on"] = true
elseif cmd == "turn_off" then
wledPayload["on"] = false
-- === 2. 亮度控制 (0-255) ===
elseif cmd == "set_brightness" then
if inputData.brightness then
wledPayload["bri"] = tonumber(inputData.brightness)
end
-- === 3. 颜色控制 (最关键部分) ===
elseif cmd == "set_color" then
-- 强制转换为数字,防止字符串 "255" 导致错误
local r = tonumber(inputData.r) or 0
local g = tonumber(inputData.g) or 0
local b = tonumber(inputData.b) or 0
-- 构造 WLED 需要的各种嵌套
-- 结构: {"seg": [{"col": [[r,g,b]], "fx": 0}], "on": true}
local colorArray = {r, g, b}
local colSegment = { colorArray } -- 这变成了 [[r,g,b]]
wledPayload["on"] = true -- 确保开灯
wledPayload["seg"] = {
{
["col"] = colSegment,
["fx"] = 0 -- 0=Solid(纯色),必须设置,否则如果当前是呼吸灯,改颜色无效
}
}
-- === 4. 特效控制 (Effect) ===
elseif cmd == "set_effect" then
if inputData.effect then
wledPayload["on"] = true
wledPayload["seg"] = {
{ ["fx"] = tonumber(inputData.effect) }
}
end
-- === 5. 特效速度/强度 ===
elseif cmd == "set_effect_speed" then
if inputData.speed then
wledPayload["seg"] = { { ["sx"] = tonumber(inputData.speed) } }
end
elseif cmd == "set_effect_intensity" then
if inputData.intensity then
wledPayload["seg"] = { { ["ix"] = tonumber(inputData.intensity) } }
end
-- === 6. 预设 (Preset) ===
elseif cmd == "set_preset" then
if inputData.preset then
wledPayload["ps"] = tonumber(inputData.preset)
end
-- === 7. 自定义透传 (高级) ===
elseif cmd == "custom" and inputData.data then
return json.encode(inputData.data)
else
-- 如果没有匹配到 command,原样返回,防止误伤
return msg
end
-- 返回标准 WLED JSON 字符串
return json.encode(wledPayload)
end
配置好之后如图

开始测试
1. 基础控制 (Basic)
最常用的开关和亮度调节。
关灯
{ "command": "turn_off" }
开灯
{ "command": "turn_on" }
亮度:最亮 (100%)
{ "command": "set_brightness", "brightness": 255 }
亮度:微光 (10%)
适合夜灯模式
{ "command": "set_brightness", "brightness": 25 }
2. 颜色控制 (Color)
使用 set_color,脚本会自动把你的 RGB 值封装成 WLED 需要的复杂数组。
纯绿 (Green)
{ "command": "set_color", "r": 0, "g": 255, "b": 0 }
纯蓝 (Blue)
{ "command": "set_color", "r": 0, "g": 0, "b": 255 }
暖白 (Warm White - 模拟白炽灯)
这是 RGB 混合出的暖白,如果你是 RGBW 灯带,可以用后面的高级指令控制白光通道
{ "command": "set_color", "r": 255, "g": 147, "b": 41 }
冷白 (Cool White)
{ "command": "set_color", "r": 201, "g": 226, "b": 255 }
3. 特效控制 (Effects)
这是 WLED 的灵魂。通过组合 特效ID + 速度 + 强度,你可以创造无限可能。
💡 小贴士:特效 ID (Effect ID) 是 WLED 内置的编号。
0: 纯色 (Solid)
1: 闪烁 (Blink)
2: 呼吸 (Breathe)
8: 彩虹 (Rainbow)
9: 彩虹闪烁 (Rainbow Glitter)
12: 火焰 (Fire 2012)
41: 骇客帝国 (Matrix)
启动“彩虹循环” (Rainbow)
{ "command": "set_effect", "effect": 8 }
调节特效:速度极快
范围 0-255,值越大越快
{ "command": "set_effect_speed", "speed": 230 }
调节特效:慢速优雅
{ "command": "set_effect_speed", "speed": 30 }
调节特效:高强度 (密度大/闪烁猛)
范围 0-255
{ "command": "set_effect_intensity", "intensity": 200 }
组合拳:慢速呼吸效果
(因为脚本逻辑是分发的,你可以连续发这三条,或者用下面的“高级自定义”一次性发完)
{"command": "set_effect", "effect": 2}
{"command": "set_effect_speed", "speed": 40}
{"command": "set_effect_intensity", "intensity": 128}
4. 调色板 (Palettes)
即使是同一个特效(比如“呼吸”),配合不同的调色板,感觉完全不同。
💡 调色板 ID 参考:
0: 默认 (Default)
2: 随机主色 (Primary Color)
5: 海洋 (Ocean) - 蓝青色调
11: 彩虹 (Rainbow)
35: 樱花 (Sakura) - 粉红/白
切换到“海洋”色调
{ "command": "set_palette", "palette": 5 }
切换到“派对”色调 (Party)
{ "command": "set_palette", "palette": 6 }
5. 预设控制 (Presets)
如果你在 WLED 网页端保存了喜欢的场景(Preset),可以直接调用。这是最方便的场景切换方式。
调用 1 号预设
{ "command": "set_preset", "preset": 1 }
调用 2 号预设
{ "command": "set_preset", "preset": 2 }
6. 👑 高级自定义 (God Mode)
利用脚本中的 custom 指令,你可以绕过简单的翻译逻辑,直接向 WLED 发送原生指令。这能实现非常复杂的功能。
场景 A:分区控制 (Segments)
把灯带分成两截,前10个灯珠显示红色,后面的显示蓝色呼吸特效。
(假设你有至少20个灯珠)
{
"command": "custom",
"data": {
"on": true,
"seg": [
{
"id": 0,
"start": 0,
"stop": 10,
"col": [[255, 0, 0]],
"fx": 0
},
{
"id": 1,
"start": 10,
"stop": 20,
"col": [[0, 0, 255]],
"fx": 2,
"sx": 128
}
]
}
}
场景 B:开启夜灯模式 (Nightlight)
开启后,灯光会在60分钟内逐渐变暗直到关闭。
{
"command": "custom",
"data": {
"nl": {
"on": true,
"dur": 60,
"mode": 1
}
}
}
dur: 持续时间(分钟)
mode: 1 (淡出到关灯)
场景 C:RGBW 控制 (针对带白光的灯带)
如果你有单独的白色通道,用 set_color 是控制不了的,必须用 custom。
格式:[R, G, B, W]
{
"command": "custom",
"data": {
"seg": [{
"col": [[0, 0, 0, 255]]
}]
}
}
这会把 RGB 关掉,只把白色通道开到最大。
场景 D:清除所有特效,恢复默认
如果玩乱了,发这个重置。
{
"command": "custom",
"data": {
"on": true,
"bri": 128,
"seg": [{
"id": 0,
"start": 0,
"stop": 1000,
"fx": 0,
"sx": 128,
"ix": 128,
"col": [[255, 160, 0]]
}]
}
}
现在你可以把这些 JSON 保存到你的测试工具或者文档里,随意组合,实现对Wled的完全掌控!