Coverage Report

Created: 2026-03-27 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/connectedhomeip/src/app/clusters/power-source-server/CodegenIntegration.cpp
Line
Count
Source
1
/*
2
 *    Copyright (c) 2022 Project CHIP Authors
3
 *
4
 *    Licensed under the Apache License, Version 2.0 (the "License");
5
 *    you may not use this file except in compliance with the License.
6
 *    You may obtain a copy of the License at
7
 *
8
 *        http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *    Unless required by applicable law or agreed to in writing, software
11
 *    distributed under the License is distributed on an "AS IS" BASIS,
12
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *    See the License for the specific language governing permissions and
14
 *    limitations under the License.
15
 */
16
17
/****************************************************************************
18
 * @file
19
 * @brief Implementation for the Power Source Server Cluster
20
 ***************************************************************************/
21
22
#include "power-source-server.h"
23
24
#include <app-common/zap-generated/cluster-objects.h>
25
#include <app-common/zap-generated/ids/Attributes.h>
26
#include <app/AttributeAccessInterfaceRegistry.h>
27
#include <app/util/attribute-storage.h>
28
#include <app/util/config.h>
29
#include <clusters/PowerSource/Metadata.h>
30
#include <lib/support/CodeUtils.h>
31
#include <lib/support/logging/CHIPLogging.h>
32
33
using namespace chip;
34
using namespace app;
35
using namespace app::Clusters;
36
using namespace app::Clusters::PowerSource::Attributes;
37
38
namespace {
39
40
struct PowerSourceClusterInfo
41
{
42
0
    PowerSourceClusterInfo() : mClusterEndpoint(kInvalidEndpointId) {}
43
0
    explicit PowerSourceClusterInfo(EndpointId powerClusterEndpointId) : mClusterEndpoint(powerClusterEndpointId) {}
44
    void Clear()
45
0
    {
46
0
        mBuf.Free();
47
0
        mEndpointList = Span<EndpointId>();
48
0
    }
49
    CHIP_ERROR SetEndpointList(Span<EndpointId> endpointList)
50
0
    {
51
0
        Clear();
52
0
        if (endpointList.size() == 0)
53
0
        {
54
0
            mEndpointList = Span<EndpointId>();
55
0
            return CHIP_NO_ERROR;
56
0
        }
57
0
        mBuf.Calloc(endpointList.size());
58
0
        if (mBuf.Get() == nullptr)
59
0
        {
60
0
            return CHIP_ERROR_NO_MEMORY;
61
0
        }
62
0
        memcpy(mBuf.Get(), endpointList.data(), endpointList.size() * sizeof(EndpointId));
63
0
        mEndpointList = Span<EndpointId>(mBuf.Get(), endpointList.size());
64
0
        return CHIP_NO_ERROR;
65
0
    }
66
    EndpointId mClusterEndpoint = kInvalidEndpointId;
67
    Platform::ScopedMemoryBuffer<EndpointId> mBuf;
68
    Span<EndpointId> mEndpointList;
69
};
70
71
PowerSourceServer gPowerSourceServer;
72
73
PowerSourceAttrAccess gAttrAccess;
74
75
static constexpr uint16_t kNumStaticEndpoints = MATTER_DM_POWER_SOURCE_CLUSTER_SERVER_ENDPOINT_COUNT;
76
#define POWER_SERVER_NUM_SUPPORTED_ENDPOINTS                                                                                       \
77
    (MATTER_DM_POWER_SOURCE_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
78
static constexpr size_t kNumSupportedEndpoints = POWER_SERVER_NUM_SUPPORTED_ENDPOINTS;
79
80
#if POWER_SERVER_NUM_SUPPORTED_ENDPOINTS > 0
81
PowerSourceClusterInfo sPowerSourceClusterInfo[kNumSupportedEndpoints] = {};
82
#else
83
PowerSourceClusterInfo * sPowerSourceClusterInfo = nullptr;
84
#endif
85
86
} // anonymous namespace
87
88
void MatterPowerSourcePluginServerInitCallback()
89
0
{
90
0
    AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess);
91
0
}
92
93
void MatterPowerSourcePluginServerShutdownCallback()
94
0
{
95
0
    AttributeAccessInterfaceRegistry::Instance().Unregister(&gAttrAccess);
96
0
}
97
98
namespace chip {
99
namespace app {
100
namespace Clusters {
101
102
CHIP_ERROR PowerSourceAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
103
0
{
104
0
    CHIP_ERROR err = CHIP_NO_ERROR;
105
106
0
    switch (aPath.mAttributeId)
107
0
    {
108
0
    case ActiveBatFaults::Id:
109
        // TODO: Needs implementation.
110
0
        err = aEncoder.EncodeEmptyList();
111
0
        break;
112
0
    case EndpointList::Id: {
113
0
        PowerSourceServer & server    = PowerSourceServer::Instance();
114
0
        const Span<EndpointId> * span = server.GetEndpointList(aPath.mEndpointId);
115
0
        if (span == nullptr)
116
0
        {
117
0
            err = aEncoder.EncodeEmptyList();
118
0
        }
119
0
        else
120
0
        {
121
0
            err = aEncoder.EncodeList([span](const auto & encoder) -> CHIP_ERROR {
122
0
                for (auto id : *span)
123
0
                {
124
0
                    ReturnErrorOnFailure(encoder.Encode(id));
125
0
                }
126
0
                return CHIP_NO_ERROR;
127
0
            });
128
0
        }
129
0
        break;
130
0
    }
131
0
    case ClusterRevision::Id: {
132
0
        err = aEncoder.Encode(PowerSource::kRevision);
133
0
        break;
134
0
    }
135
0
    default:
136
0
        break;
137
0
    }
138
139
0
    return err;
140
0
}
141
142
PowerSourceAttrAccess & TestOnlyGetPowerSourceAttrAccess()
143
0
{
144
0
    return gAttrAccess;
145
0
}
146
147
PowerSourceServer & PowerSourceServer::Instance()
148
0
{
149
0
    return gPowerSourceServer;
150
0
}
151
152
// Caller does not need to retain the span past the call point as these are copied into an internal storage
153
CHIP_ERROR PowerSourceServer::SetEndpointList(EndpointId powerSourceClusterEndpoint, Span<EndpointId> endpointList)
154
0
{
155
    // TODO: should check here that the power source cluster exists on the endpoint, but for now let's take the caller's word
156
    // for it
157
0
    uint16_t idx = emberAfGetClusterServerEndpointIndex(powerSourceClusterEndpoint, Clusters::PowerSource::Id, kNumStaticEndpoints);
158
0
    if (idx == kEmberInvalidEndpointIndex)
159
0
    {
160
0
        return CHIP_ERROR_NO_MEMORY;
161
0
    }
162
163
0
    sPowerSourceClusterInfo[idx].Clear();
164
0
    if (endpointList.size() == 0)
165
0
    {
166
0
        sPowerSourceClusterInfo[idx] = PowerSourceClusterInfo();
167
0
        return CHIP_NO_ERROR;
168
0
    }
169
170
0
    sPowerSourceClusterInfo[idx] = PowerSourceClusterInfo(powerSourceClusterEndpoint);
171
0
    return sPowerSourceClusterInfo[idx].SetEndpointList(endpointList);
172
0
}
173
const Span<EndpointId> * PowerSourceServer::GetEndpointList(EndpointId powerSourceClusterEndpoint) const
174
0
{
175
0
    uint16_t idx = emberAfGetClusterServerEndpointIndex(powerSourceClusterEndpoint, Clusters::PowerSource::Id, kNumStaticEndpoints);
176
0
    if (idx != kEmberInvalidEndpointIndex && sPowerSourceClusterInfo[idx].mEndpointList.size() > 0)
177
0
    {
178
0
        return &sPowerSourceClusterInfo[idx].mEndpointList;
179
0
    }
180
0
    return nullptr;
181
0
}
182
183
void PowerSourceServer::Shutdown()
184
0
{
185
0
#if POWER_SERVER_NUM_SUPPORTED_ENDPOINTS > 0
186
0
    for (size_t i = 0; i < kNumSupportedEndpoints; ++i)
187
0
    {
188
0
        sPowerSourceClusterInfo[i].Clear();
189
0
    }
190
0
#endif
191
0
}
192
193
size_t PowerSourceServer::GetNumSupportedEndpointLists() const
194
0
{
195
0
    return kNumSupportedEndpoints;
196
0
}
197
198
} // namespace Clusters
199
} // namespace app
200
} // namespace chip