ocy
(wuzhou-ouchangyun)
2026 年6 月 23 日 08:16
1
问题描述
参考新增组件,对资源协作接口的属性进行订阅,已参考基于资源协作接口的订阅机制指导 | 文档中心 | openUBMC 该文档,但是始终无法获取属性变化通知,请问是什么原因?
定位过程
service.json文件新增
{
"name": "my_app",
"type": "application",
"deployConfig": "",
"version": "0.0.1",
"user": "test",
"license": "",
"codegen_policy": {
"version": "18"
},
"description": "",
"dependencies": {
"test": [
],
"build": [
{
"conan": "libmc4lua/[>=0.0.1]"
},
{
"conan": "mdb_interface/[>=0.0.1]"
}
]
},
"required": [
{
"path": "/bmc/kepler/Systems/${SystemId}/FruCtrl/${Id}",
"interface": "bmc.kepler.Systems.FruCtrl",
"properties": {
"PowerState": ["subscribe"]
}
}
]
}
通过bmcgo gen 自动生成代码,client.lua 中已有对应的接口
function my_app_client:OnFruCtrlPropertiesChanged(cb, path_params)
local path_namespace = path_params and
('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/FruCtrl/' .. path_params['Id']) or
'/bmc/kepler/Systems/:SystemId/FruCtrl/:Id'
self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), path_namespace,
cb, 'bmc.kepler.Systems.FruCtrl', {'PowerState'})
end
my_app_app.lua中代码如下
local class = require 'mc.class'
local service = require 'my_app.service'
local my_app_client = require 'my_app.client'
local logging = require 'mc.logging'
local my_app = class(service)
function my_app:ctor()
end
function my_app:init()
self.super.init(self)
logging:notice("my_app init")
my_app_client:OnFruCtrlPropertiesChanged(function(values, path)
if values['PowerState'] then
logging:notice("power state change")
end
local system_id = tonumber(string.match(path or '', '/bmc/kepler/Systems/(%d+)/FruCtrl'))
logging:notice("OnFruCtrlPropertiesChanged state system_id %d", system_id)
end)
logging:notice("my_app init end")
end
return my_app
mdbctl setprop 设置PowerState属性,通过busctl --user monitor bmc.kepler.fructrl 能监听对应的信号变化,
my_app init和my_app init end都有打印,但是power state change未有打印,情况与订阅属性变化信号无法正常捕获到 初始一致,但是未能从文档中分析出来哪里存在差异,导致订阅属性变更失败,请问是以上哪里存在问题?还是需要其他进行配置?
环境信息
重现步骤
答案内容由AI生成,仅供参考:
根据您提供的详细问题描述、代码以及上下文信息,问题的核心原因很可能在于您订阅的属性 PowerState 在定义时,其 emitsChangedSignal 属性被设置为了 false、const 或 invalidates,导致即使属性值发生了变化,D-Bus 上也没有发出携带属性值的 PropertiesChanged 信号,您的回调函数自然无法被触发。
以下是基于上下文信息的具体分析和相应的排查与解决方案:
1. 根本原因分析:emitsChangedSignal 属性配置不当
关键证据 :在您提供的 基于资源协作接口的订阅机制指导 文档片段中明确指出:
emitsChangedSignal 表示是否发送属性变化信号,默认为 "true"
如果取值为 false,表示属性变化时不发送信号;
如果取值为 const,表示属性永不变化,不需要发送信号;
如果取值为 true,表示属性变化时发送信号,信号携带属性值;
如果取值为 invalidates,表示属性变化时发送信号,但信号不携带属性值;
问题关联 :您提到 busctl --user monitor bmc.kepler.fructrl 能监听到信号变化,这说明 D-Bus 信号本身是在发送的。但您的回调函数 OnFruCtrlPropertiesChanged 是通过 subscribe_signal.on_properties_changed 实现的,它依赖的是标准的 org.freedesktop.DBus.Properties.PropertiesChanged 信号,并且该信号必须携带变化后的属性值 。
结论 :如果 PowerState 属性的定义中 "emitsChangedSignal" 被设置为 "invalidates"(只发信号不带值)或 "false"/"const"(完全不发信号),那么 subscribe_signal.on_properties_changed 机制将无法捕获到符合其预期的、携带值的信号,从而导致回调函数不被执行。您虽然通过 busctl 捕捉到了一些信号,但这些信号可能并非 PropertiesChanged,或者是 PropertiesChanged 但因 invalidates 选项而未包含 PowerState 值。
2. 排查步骤与解决方案
请按照以下步骤进行排查和修复:
步骤一:检查 FruCtrl.json 中 PowerState 属性的定义
操作 :找到定义 FruCtrl 接口的 JSON 文件(根据您提供的代码,路径应为 mdb_interface 仓库下的 json/intf/mdb/bmc/kepler/Systems/FruCtrl.json 或其项目内的等效文件)。
关键检查点 :查找 PowerState 属性对应的定义,确认其 options 块中的 emitsChangedSignal 字段的取值。
理想值 :应为 "true"(或直接省略,因为默认值为 true)。
问题值 :如果发现是 "false"、"const" 或 "invalidates",请将其修改为 "true" 或直接删除该行。
步骤二:验证 subscribe_signal.on_properties_changed 的返回值
操作 :在您的 my_app_client:OnFruCtrlPropertiesChanged 函数中,打印 subscribe_signal.on_properties_changed 的返回值,检查其是否为一个有效的标识符。
代码示例(用于调试) :function my_app_client:OnFruCtrlPropertiesChanged(cb, path_params)
-- ... 路径构建逻辑 ...
local slot_id = subscribe_signal.on_properties_changed(self:get_bus(), path_namespace,
cb, 'bmc.kepler.Systems.FruCtrl', {'PowerState'})
print("subscription slot id: " .. tostring(slot_id)) -- 检查是否成功返回了标识符
self.signal_slots[#self.signal_slots + 1] = slot_id
-- 注:为简单起见,这里直接使用了 print,实际应使用 logging
end
预期结果 :应打印出类似 subscription slot id: 1 的信息。如果返回 nil,则说明订阅本身可能就失败了。
步骤三:检查回调函数签名
操作 :确认您的回调函数签名是否与 subscribe_signal.on_properties_changed 的预期一致。
预期签名 :function(changed_properties, path)。
changed_properties:是一个table ,包含所有变化了的属性及其新值。
path:是发生变化的对象的 D-Bus 路径。
您的代码检查 :您的回调函数中使用了 if values['PowerState'] then ... end,这是正确的。但请确认 values 参数确实是被传入的 changed_properties table。
步骤四:确认 my_app 服务已正确启动并连接到 D-Bus
操作 :确保 my_app 应用在 systemd 或类似进程管理器中正常启动,并且其 user 字段(您设置的是 test)具有访问目标 D-Bus 接口的权限。
日志检查 :查看系统日志(如 journalctl -u my_app),确认 my_app init 和 my_app init end 日志打印正常,并且没有其他错误日志(如连接失败、权限拒绝等)。
特别注意 :您的问题标题提到了“新增对象不上树问题分析”,其中提到了由于 systemd 配置文件未裁剪导致重复的进程拉起 。请务必检查您的服务是否被重复启动了,这可能导致 D-Bus 注册异常,从而影响信号订阅。
步骤五:参考官方示例和最佳实践
再次详细阅读您提到的 基于资源协作接口的订阅机制指导 文档。
重点核对 文档中关于 required 字段定义的格式。您的 service.json 中 required 字段的定义看起来是正确的,但请务必确认 properties 子项的格式完全匹配文档要求。
总结排查清单
排查项
预期结果
您的现状
建议操作
1. emitsChangedSignal
应为 true 或不存在(默认)
可能为 false/const/invalidates
立即检查并修改
2. 订阅返回值
应为一个非 nil 的标识符
未知
添加日志打印确认
3. 回调函数签名
function(table, string)
您已使用正确
确认参数是否按预期传递
4. 服务状态与权限
正常运行,无重复进程,D-Bus连接正常
未知
检查系统日志和进程状态
5. service.json格式
严格匹配文档规范
您的写法看起来正确
逐字比对文档示例
最可能的解决方案 :请您优先检查并修正目标属性 PowerState 在接口定义文件中的 emitsChangedSignal 配置。将问题属性的该配置设置为 true 后,重新部署并测试,很大概率能解决您的问题。
感觉有可能是你这个组件启动比较快,fructrl的接口还未注册上树,所以订阅失败