-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--          http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.
local mdb = require 'mc.mdb'
local class = require 'mc.class'
local app_base = require 'mc.client_app_base'
local mdb_service = require 'mc.mdb.mdb_service'
local subscribe_signal = require 'mc.mdb.subscribe_signal'
local org_freedesktop_dbus = require 'sd_bus.org_freedesktop_dbus'

local match_rule = org_freedesktop_dbus.MatchRule
local get_non_virtual_interface_objects = mdb_service.get_non_virtual_interface_objects
local foreach_non_virtual_interface_objects = mdb_service.foreach_non_virtual_interface_objects

local FruCtrl = require 'pcie_device.json_types.FruCtrl'
local Connector = require 'pcie_device.json_types.Connector'
local Component = require 'pcie_device.json_types.Component'
local BlockIO = require 'pcie_device.json_types.BlockIO'
local Accessor = require 'pcie_device.json_types.Accessor'
local SmBios = require 'pcie_device.json_types.SmBios'
local Bios = require 'pcie_device.json_types.Bios'
local Unit = require 'pcie_device.json_types.Unit'
local Events = require 'pcie_device.json_types.Events'
local Processor = require 'pcie_device.json_types.Processor'
local NPU = require 'pcie_device.json_types.NPU'
local Package = require 'pcie_device.json_types.Package'
local CPU = require 'pcie_device.json_types.CPU'

---@class pcie_device_client: BasicClient
local pcie_device_client = class(app_base.Client)

function pcie_device_client:GetFruCtrlObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruCtrl', true)
end

function pcie_device_client:ForeachFruCtrlObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruCtrl', cb, true)
end

function pcie_device_client:GetConnectorObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Connector', true)
end

function pcie_device_client:ForeachConnectorObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Connector', cb, true)
end

function pcie_device_client:GetComponentObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Component', true)
end

function pcie_device_client:ForeachComponentObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Component', cb, true)
end

function pcie_device_client:GetBlockIOObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Chip.BlockIO', true)
end

function pcie_device_client:ForeachBlockIOObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Chip.BlockIO', cb, true)
end

function pcie_device_client:GetAccessorObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Accessor', true)
end

function pcie_device_client:ForeachAccessorObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Accessor', cb, true)
end

function pcie_device_client:GetSmBiosObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.SmBios', true)
end

function pcie_device_client:ForeachSmBiosObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.SmBios', cb, true)
end

function pcie_device_client:GetBiosObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Bios', true)
end

function pcie_device_client:ForeachBiosObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Bios', cb, true)
end

function pcie_device_client:GetUnitObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Board.Unit', true)
end

function pcie_device_client:ForeachUnitObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Board.Unit', cb, true)
end

function pcie_device_client:GetProcessorObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Processor', true)
end

function pcie_device_client:ForeachProcessorObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Processor', cb, true)
end

function pcie_device_client:GetNPUObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Processor.NPU', true)
end

function pcie_device_client:ForeachNPUObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Processor.NPU', cb, true)
end

function pcie_device_client:GetPackageObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Managers.Package', true)
end

function pcie_device_client:ForeachPackageObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Managers.Package', cb, true)
end

function pcie_device_client:GetCPUObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Processor.CPU', true)
end

function pcie_device_client:ForeachCPUObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Processor.CPU', cb, true)
end

function pcie_device_client:OnFruCtrlPropertiesChanged(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruCtrl', {'PowerState'})
end

function pcie_device_client:OnFruCtrlInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruCtrl')
end

function pcie_device_client:OnFruCtrlInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruCtrl')
end

function pcie_device_client:OnConnectorInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Connector')
end

function pcie_device_client:OnConnectorInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Connector')
end

function pcie_device_client:OnComponentPropertiesChanged(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Component', {'Name'})
end

function pcie_device_client:OnComponentInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Component')
end

function pcie_device_client:OnComponentInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Component')
end

function pcie_device_client:OnBlockIOInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Chip.BlockIO')
end

function pcie_device_client:OnBlockIOInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Chip.BlockIO')
end

function pcie_device_client:OnAccessorInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Accessor')
end

function pcie_device_client:OnAccessorInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Accessor')
end

function pcie_device_client:OnSmBiosInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.SmBios')
end

function pcie_device_client:OnSmBiosInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.SmBios')
end

function pcie_device_client:OnBiosPropertiesChanged(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Bios', {'PcieCardBDF', 'OCPCardBDF', 'PcieDiskBDF'})
end

function pcie_device_client:OnBiosInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Bios')
end

function pcie_device_client:OnBiosInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Bios')
end

function pcie_device_client:OnUnitInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Board.Unit')
end

function pcie_device_client:OnUnitInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Board.Unit')
end

function pcie_device_client:GetEventsEventsObject(path_params)
    return mdb.try_get_object(self:get_bus(),
        path_params and ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Events') or
            '/bmc/kepler/Systems/:SystemId/Events', 'bmc.kepler.Systems.Events')
end

function pcie_device_client:GetEventsObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Events', true,
        {'/bmc/kepler/Systems/:SystemId/Events'})
end

function pcie_device_client:ForeachEventsObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Events', cb, true,
        {'/bmc/kepler/Systems/:SystemId/Events'})
end

function pcie_device_client:OnEventsInterfacesAdded(cb, path_params)
    local path_namespace = path_params and ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Events') or
                               '/bmc/kepler/Systems/:SystemId/Events'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), path_namespace, cb,
        'bmc.kepler.Systems.Events')
end

function pcie_device_client:OnEventsInterfacesRemoved(cb, path_params)
    local path_namespace = path_params and ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Events') or
                               '/bmc/kepler/Systems/:SystemId/Events'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), path_namespace,
        cb, 'bmc.kepler.Systems.Events')
end

function pcie_device_client:OnProcessorInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Processor')
end

function pcie_device_client:OnProcessorInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Processor')
end

function pcie_device_client:OnNPUInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Processor.NPU')
end

function pcie_device_client:OnNPUInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Processor.NPU')
end

function pcie_device_client:OnPackageInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Managers.Package')
end

function pcie_device_client:OnPackageInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Managers.Package')
end

function pcie_device_client:OnCPUInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Processor.CPU')
end

function pcie_device_client:OnCPUInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Processor.CPU')
end

---@param EventCode string
---@param Enabled integer
---@param ObjectIndex integer
---@param MockState integer
---@return Events.MockEventRsp
function pcie_device_client:EventsEventsMockEvent(ctx, path_params, EventCode, Enabled, ObjectIndex, MockState)
    local req = Events.MockEventReq.new(EventCode, Enabled, ObjectIndex, MockState):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.MockEventRsp.new(obj:MockEvent(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsMockEvent(ctx, path_params, EventCode, Enabled, ObjectIndex, MockState)
    return pcall(function()
        local req = Events.MockEventReq.new(EventCode, Enabled, ObjectIndex, MockState):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.MockEventRsp.new(obj:MockEvent(ctx, req:unpack(true)))
    end)
end

---@param StartId integer
---@param Count integer
---@param QueryParameters Events.KeyValueTable[]
---@return Events.GetAlarmListRsp
function pcie_device_client:EventsEventsGetAlarmList(ctx, path_params, StartId, Count, QueryParameters)
    local req = Events.GetAlarmListReq.new(StartId, Count, QueryParameters):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.GetAlarmListRsp.new(obj:GetAlarmList(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsGetAlarmList(ctx, path_params, StartId, Count, QueryParameters)
    return pcall(function()
        local req = Events.GetAlarmListReq.new(StartId, Count, QueryParameters):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.GetAlarmListRsp.new(obj:GetAlarmList(ctx, req:unpack(true)))
    end)
end

---@param StartId integer
---@param Count integer
---@param QueryParameters Events.KeyValueTable[]
---@return Events.GetEventListRsp
function pcie_device_client:EventsEventsGetEventList(ctx, path_params, StartId, Count, QueryParameters)
    local req = Events.GetEventListReq.new(StartId, Count, QueryParameters):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.GetEventListRsp.new(obj:GetEventList(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsGetEventList(ctx, path_params, StartId, Count, QueryParameters)
    return pcall(function()
        local req = Events.GetEventListReq.new(StartId, Count, QueryParameters):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.GetEventListRsp.new(obj:GetEventList(ctx, req:unpack(true)))
    end)
end

---@return Events.ClearEventListRsp
function pcie_device_client:EventsEventsClearEventList(ctx, path_params)
    local obj = self:GetEventsEventsObject(path_params)

    return Events.ClearEventListRsp.new(obj:ClearEventList(ctx))
end

function pcie_device_client:PEventsEventsClearEventList(ctx, path_params)
    return pcall(function()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.ClearEventListRsp.new(obj:ClearEventList(ctx))
    end)
end

---@return Events.GetEventInfoRsp
function pcie_device_client:EventsEventsGetEventInfo(ctx, path_params)
    local obj = self:GetEventsEventsObject(path_params)

    return Events.GetEventInfoRsp.new(obj:GetEventInfo(ctx))
end

function pcie_device_client:PEventsEventsGetEventInfo(ctx, path_params)
    return pcall(function()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.GetEventInfoRsp.new(obj:GetEventInfo(ctx))
    end)
end

---@param EventCode string
---@param MaskState integer
---@param Mode integer
---@return Events.MaskEventRsp
function pcie_device_client:EventsEventsMaskEvent(ctx, path_params, EventCode, MaskState, Mode)
    local req = Events.MaskEventReq.new(EventCode, MaskState, Mode):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.MaskEventRsp.new(obj:MaskEvent(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsMaskEvent(ctx, path_params, EventCode, MaskState, Mode)
    return pcall(function()
        local req = Events.MaskEventReq.new(EventCode, MaskState, Mode):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.MaskEventRsp.new(obj:MaskEvent(ctx, req:unpack(true)))
    end)
end

---@return Events.GetMaskedEventListRsp
function pcie_device_client:EventsEventsGetMaskedEventList(ctx, path_params)
    local obj = self:GetEventsEventsObject(path_params)

    return Events.GetMaskedEventListRsp.new(obj:GetMaskedEventList(ctx))
end

function pcie_device_client:PEventsEventsGetMaskedEventList(ctx, path_params)
    return pcall(function()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.GetMaskedEventListRsp.new(obj:GetMaskedEventList(ctx))
    end)
end

---@param EventInfo Events.KeyValueTable[]
---@return Events.AddEventRsp
function pcie_device_client:EventsEventsAddEvent(ctx, path_params, EventInfo)
    local req = Events.AddEventReq.new(EventInfo):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.AddEventRsp.new(obj:AddEvent(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsAddEvent(ctx, path_params, EventInfo)
    return pcall(function()
        local req = Events.AddEventReq.new(EventInfo):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.AddEventRsp.new(obj:AddEvent(ctx, req:unpack(true)))
    end)
end

---@param Path string
---@return Events.ExportEventRsp
function pcie_device_client:EventsEventsExportEvent(ctx, path_params, Path)
    local req = Events.ExportEventReq.new(Path):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.ExportEventRsp.new(obj:ExportEvent(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsExportEvent(ctx, path_params, Path)
    return pcall(function()
        local req = Events.ExportEventReq.new(Path):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.ExportEventRsp.new(obj:ExportEvent(ctx, req:unpack(true)))
    end)
end

---@param EventName string[]
---@return Events.CheckEventNameRsp
function pcie_device_client:EventsEventsCheckEventName(ctx, path_params, EventName)
    local req = Events.CheckEventNameReq.new(EventName):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.CheckEventNameRsp.new(obj:CheckEventName(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsCheckEventName(ctx, path_params, EventName)
    return pcall(function()
        local req = Events.CheckEventNameReq.new(EventName):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.CheckEventNameRsp.new(obj:CheckEventName(ctx, req:unpack(true)))
    end)
end

---@param AlarmName string
---@return Events.SetAlarmNameRsp
function pcie_device_client:EventsEventsSetAlarmName(ctx, path_params, AlarmName)
    local req = Events.SetAlarmNameReq.new(AlarmName):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.SetAlarmNameRsp.new(obj:SetAlarmName(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsSetAlarmName(ctx, path_params, AlarmName)
    return pcall(function()
        local req = Events.SetAlarmNameReq.new(AlarmName):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.SetAlarmNameRsp.new(obj:SetAlarmName(ctx, req:unpack(true)))
    end)
end

---@param EventCode string
---@param Severity integer
---@return Events.SetEventSeverityRsp
function pcie_device_client:EventsEventsSetEventSeverity(ctx, path_params, EventCode, Severity)
    local req = Events.SetEventSeverityReq.new(EventCode, Severity):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.SetEventSeverityRsp.new(obj:SetEventSeverity(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsSetEventSeverity(ctx, path_params, EventCode, Severity)
    return pcall(function()
        local req = Events.SetEventSeverityReq.new(EventCode, Severity):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.SetEventSeverityRsp.new(obj:SetEventSeverity(ctx, req:unpack(true)))
    end)
end

---@param EventKeyId string
---@param Action integer
---@return Events.SetEventActionRsp
function pcie_device_client:EventsEventsSetEventAction(ctx, path_params, EventKeyId, Action)
    local req = Events.SetEventActionReq.new(EventKeyId, Action):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.SetEventActionRsp.new(obj:SetEventAction(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsSetEventAction(ctx, path_params, EventKeyId, Action)
    return pcall(function()
        local req = Events.SetEventActionReq.new(EventKeyId, Action):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.SetEventActionRsp.new(obj:SetEventAction(ctx, req:unpack(true)))
    end)
end

---@param EventInfo Events.KeyValueTable[]
---@return Events.AddSelRsp
function pcie_device_client:EventsEventsAddSel(ctx, path_params, EventInfo)
    local req = Events.AddSelReq.new(EventInfo):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.AddSelRsp.new(obj:AddSel(ctx, req:unpack(true)))
end

function pcie_device_client:PEventsEventsAddSel(ctx, path_params, EventInfo)
    return pcall(function()
        local req = Events.AddSelReq.new(EventInfo):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.AddSelRsp.new(obj:AddSel(ctx, req:unpack(true)))
    end)
end

function pcie_device_client:SubscribeFruCtrlBeforePowerOnSignal(cb)
    local sig = match_rule.signal('BeforePowerOnSignal', 'bmc.kepler.Systems.FruCtrl')
    self.signal_slots[#self.signal_slots + 1] = self:get_bus():match(sig, function(msg)
        cb(msg:read())
    end)
end

function pcie_device_client:ctor()
    self.signal_slots = {}
end

---@type pcie_device_client
return pcie_device_client.new('pcie_device')
