31 极物科技 | Control4 对接 - CAN 继电器驱动

极物科技 | Control4 对接 - CAN 继电器驱动

前言

在智能控制领域,"协议壁垒"与"系统稳定性"始终是绕不开的难题。极物科技(Zeewo)以 "重构空间交互体验" 为使命,通过自研的 极物 OS,实现了 KNX、DALI、CAN、RS485 等多种总线协议在单一主机上的深度融合。

我们认为,一个真正优秀的智能系统,不仅要实现灯光、遮阳、温控、音乐、安防等全生态设备的无界融合 ,更要确保本地运行、断网可用 ,并具备WEB 远程调试OTA 固件升级的能力。基于此底层架构,我们推出了诸如带双路 DALI 的 KNX 主机、HomeKit 网桥等核心硬件,并将极物 OS 成功接入了 Apple HomeKit、小度、纯血鸿蒙及 HomeAssistant 等主流生态系统。

一句话概述:本文详细解析极物网关 CAN 继电器驱动的 Control4 DriverWorks 实现,涵盖多路继电器控制、状态同步、Proxy 代理机制及高级场景定时。

本文聚焦于 极物 CAN 继电器驱动的完整实现,从多路继电器结构体、Proxy 代理分发、状态同步机制到高级场景定时,逐一深入剖析,并提供完整代码供 C4 集成商参考。


1. 驱动概述

1.1 驱动定位

CAN 继电器驱动是 Control4 系统中直接面向终端用户的继电器设备驱动,负责:

  • 接收 C4 Composer 或场景的继电器开关控制指令
  • 通过多路 Proxy 架构分别控制每个继电器通道
  • 接收网关下发的继电器状态更新
  • 支持高级场景定时调用

1.2 驱动文件结构

复制代码
Aolebach-Can-Relay/
├── driver.xml              # 驱动元数据与配置定义
├── driver.lua              # 驱动主逻辑(入口、命令路由、Proxy 分发)
├── can.lua                 # CAN 协议封装(继电器控制指令构造)
├── proxy.lua               # Proxy 代理逻辑(继电器控制、状态更新)
├── action.lua              # 动作处理
├── adance_sence_timer.lua  # 高级场景定时
├── const.lua               # 常量定义(Proxy ID、设备结构体)
├── documentation.rtf       # 驱动文档说明
└── Aolebach-CAN-RELAY.c4zproj  # C4 Composer 工程文件

1.3 通讯参数

参数 规格
网关 Proxy ID 1(CAN_GATE_WAY_PROXY_ID)
继电器 1 Proxy ID 101(CAN_RELAY_PROXY_ID_1)
继电器 2 Proxy ID 102(CAN_RELAY_PROXY_ID_2)
继电器 3 Proxy ID 103(CAN_RELAY_PROXY_ID_3)
CAN ID 设备 CAN 总线地址
继电器数量 最多 3 路

2. 驱动配置(driver.xml)

xml 复制代码
<devicedata>
  <manufacturer>Aolebach</manufacturer>
  <name>奥乐巴赫 CAN 继电器 通用</name>
  <model>Relay</model>
  <version>2025011309</version>
  <control>lua_gen</control>
  <driver>DriverWorks</driver>

  <combo>True</combo>
  <proxies>
    <proxy>relay aolebahe</proxy>
  </proxies>

  <capabilities>
    <on_off>True</on_off>
  </capabilities>

  <config>
    <properties>
      <property>
        <name>CAN ID</name>
        <type>RANGED_INTEGER</type>
        <readonly>false</readonly>
        <default>0</default>
      </property>
      <property>
        <name>Debug Mode</name>
        <type>LIST</type>
        <items>
          <item>Off</item>
          <item>Print</item>
          <item>Log</item>
          <item>Print and Log</item>
        </items>
        <default>Off</default>
      </property>
    </properties>
  </config>
</devicedata>

3. 常量定义(const.lua)

lua 复制代码
-- 代理
CAN_GATE_WAY_PROXY_ID = 1

-- 继电器
CAN_RELAY_PROXY_ID_1 = 101
CAN_RELAY_PROXY_ID_2 = 102
CAN_RELAY_PROXY_ID_3 = 103

-- 按键事件
TOP_BUTTON = 0
BOTTOM_BUTTON = 1
TOGGLE_BUTTON = 2

RELEASE_BUTTON = 0
PRESS_BUTTON = 1
CLICK_BUTTON = 2

g_can_proxy_bound_status = false

-- CAN 继电器设备结构体
g_can_relay_device = {
    can_id = 0,
    object = "relay",
    relay_1 = {
        action = "off",
        sub_id = 1
    },
    relay_2 = {
        action = "off",
        sub_id = 2
    },
    relay_3 = {
        action = "off",
        sub_id = 3
    }
}

4. 驱动核心实现

4.1 属性变更回调

lua 复制代码
function OnPropertyChanged(strProperty)
    local value = Properties[strProperty]
    if (value == nil) then
        value = ''
    end

    if (strProperty == 'CAN ID') then
        g_can_relay_device.can_id = tonumber(value)
    end

    Print_table("g_can_relay_device", g_can_relay_device)
end

4.2 延迟初始化

lua 复制代码
function OnDriverLateInit(dit)
    for property, _ in pairs(Properties) do
        OnPropertyChanged(property)
    end

    gTestTimer = AddTimer(gTestTimer, 3)

    LUMI_CMD.GET_CONNECTED_STATE(CAN_GATE_WAY_PROXY_ID, nil, nil)
end

4.3 Proxy 绑定变更

lua 复制代码
function OnBindingChanged(idBinding, class, bIsBound)
    dbg("OnBindingChanged(), idBinding = " .. tostring(idBinding) .. ", class = " .. class .. ", bIsBound = " ..
            tostring(bIsBound))
    if (idBinding == CAN_GATE_WAY_PROXY_ID) then
        g_can_proxy_bound_status = bIsBound
    end
end

4.4 命令路由

lua 复制代码
function ExecuteCommand(strCommand, tParams)
    Print_table("strCommand", strCommand)
    Print_table("tParams", tParams)
    if (strCommand == "LUA_ACTION") then
        lua_normal_action(tParams)
    else
        lua_special_action(strCommand, tParams)
    end
end

5. Proxy 分发机制

lua 复制代码
function ReceivedFromProxy(idBinding, strCommand, tParams)
    if (idBinding == CAN_GATE_WAY_PROXY_ID) then
        -- 网关下发的状态更新
        proxy_relay_update_by_gateway(g_can_relay_device, strCommand, tParams)
        proxy_update_to()
    elseif (idBinding == CAN_RELAY_PROXY_ID_1) then
        -- 继电器 1 控制
        proxy_relay_control(g_can_relay_device.relay_1, strCommand, tParams, CAN_RELAY_PROXY_ID_1)
        proxy_update_to()
    elseif (idBinding == CAN_RELAY_PROXY_ID_2) then
        -- 继电器 2 控制
        proxy_relay_control(g_can_relay_device.relay_2, strCommand, tParams, CAN_RELAY_PROXY_ID_2)
        proxy_update_to()
    elseif (idBinding == CAN_RELAY_PROXY_ID_3) then
        -- 继电器 3 控制
        proxy_relay_control(g_can_relay_device.relay_3, strCommand, tParams, CAN_RELAY_PROXY_ID_2)
        proxy_update_to()
    end
end

6. CAN 协议封装(can.lua)

6.1 继电器开启

lua 复制代码
function relay_control_on(device)
    local frame_data = {
        driver_data = {
            can_id = g_can_relay_device.can_id,
            sub_id = device.sub_id,
            action = "on",
            object = g_can_relay_device.object
        },
        frame_type = "request",
        frame_driver = "can",
        frame_result = "ok"
    }

    device.action = "on"
    C4:SendToProxy(CAN_GATE_WAY_PROXY_ID, JSON:encode(frame_data), {})
end

6.2 继电器关闭

lua 复制代码
function relay_control_off(device)
    local frame_data = {
        driver_data = {
            can_id = g_can_relay_device.can_id,
            sub_id = device.sub_id,
            action = "off",
            object = g_can_relay_device.object
        },
        frame_type = "request",
        frame_driver = "can",
        frame_result = "ok"
    }

    device.action = "off"
    C4:SendToProxy(CAN_GATE_WAY_PROXY_ID, JSON:encode(frame_data), {})
end

6.3 状态更新(网关下行)

lua 复制代码
function proxy_relay_update_by_gateway(device, strCommand, tParams)
    if (strCommand == nil) then
        print("proxy_info_update error")
        return
    end

    local frame = JSON:decode(strCommand)

    -- 过滤无关信号
    if frame.driver_data.can_id ~= device.can_id or frame.driver_data.object ~= "relay" then
        return
    end

    Print_table("frame", frame.driver_data)
    Print_table("device.action", device.action)

    if frame.driver_data.sub_id == 1 then
        device.relay_1.action = frame.driver_data.action
    elseif frame.driver_data.sub_id == 2 then
        device.relay_2.action = frame.driver_data.action
    elseif frame.driver_data.sub_id == 3 then
        device.relay_3.action = frame.driver_data.action
    end
end

7. 注意事项

⚠️ CAN ID 配置

  • CAN ID 需与网关中配置的 CAN 总线地址一致

  • 每个 CAN 设备有唯一的 CAN ID
    ⚠️ 多路继电器

  • 单台设备最多支持 3 路继电器

  • 每路继电器有独立的 Proxy ID(101、102、103)

  • 各继电器通道独立工作,互不干扰
    ⚠️ 状态同步

  • 继电器状态由网关主动推送,驱动实时响应更新

  • proxy_update_to() 用于将状态同步到 C4 Composer 界面


8. 相关文档

  • 《极物科技 | Control4 对接 - 系统架构与驱动开发概述》
  • 《极物科技 | Control4 对接 - CAN 网关驱动》
  • 《极物科技 | Control4 对接 - CAN 按键面板驱动》

关于极物科技(ZEEWO)

极物科技(Zeewo)致力于为用户提供智能控制系统及硬件产品。我们以总线系统为技术底座,以**"稳定、可靠、快速响应"**为产品底线,是国内少有的拥有 KNX、DALI 全套软硬件自主研发能力的厂商之一。

我们的核心能力:

  • 系统架构:自研极物 OS,支持多协议无界融合(KNX/DALI/CAN/RS485/IP)。
  • 核心硬件:带双路 DALI 的 KNX 主机、超薄全金属定制面板、各类智选传感器及网关。
  • 生态互联:深度融入 Apple HomeKit、Matter、小度、HomeAssistant 及纯血鸿蒙生态。
  • 调试交付:独家支持 ETS 导出 XML 直接导入进行 APP 免编程调试,支持远程 WEB 运维。

我们的市场覆盖:

服务网点已覆盖全国核心城市(含长三角、珠三角、成渝等),并以高品质的方案深耕家居生活、酒店民宿、企业办公、疗愈康养、餐馆会所 等多个细分领域。

(如果您在开发或落地中遇到技术问题,欢迎通过官网或后台私信与我交流探讨)

相关推荐
阿钱真强道32 分钟前
29 极物科技 | Control4 对接 - DALI 彩色灯具驱动(DT8)
智能照明·极物·极物智能·极物科技·control4·dali调光·dt8
阿钱真强道1 天前
25 极物科技 | DALI协议栈 - DT8双色温扩展与PWM映射
极物·极物智能·极物科技·dali协议栈·智慧照明·dt8双色温·pwm映射
阿钱真强道2 天前
24 极物科技 | DALI协议栈 - 定时器与中断系统
定时器·曼彻斯特编码·极物·极物智能·极物科技·dali协议栈·智慧照明
阿钱真强道2 天前
23 极物科技 | DALI协议栈 - EEPROM持久化机制
eeprom·极物·极物智能·极物科技·iec 62386·dali协议栈·智慧照明
阿钱真强道3 天前
20 极物科技 | DALI协议栈 - 配置命令详解
智能照明·极物·极物智能·极物科技·iec 62386·dali协议栈·场景配置
阿钱真强道3 天前
22 极物科技 | DALI协议栈 - 特殊命令与设备发现机制
极物·极物智能·极物科技·iec 62386·设备发现·dali协议栈·智慧照明
逗脑IDE3 天前
零基础学ESP32:蜂鸣器——让ESP32会“唱歌”!
python·物联网·esp32·智能家居
阿钱真强道4 天前
19 极物科技 | DALI协议栈 - 标准命令集解析
极物·极物智能·极物科技·iec 62386·调光控制·dali协议栈·标准命令
阿钱真强道4 天前
17 极物科技 | DALI协议栈 - 物理层位编解码详解
曼彻斯特编码·极物·极物智能·极物科技·iec 62386·dali协议栈