Line data Source code
1 : /********************************************************************************
2 : * Copyright (c) 2026 BMW AG
3 : *
4 : * This program and the accompanying materials are made available under the
5 : * terms of the Apache License Version 2.0 which is available at
6 : * https://www.apache.org/licenses/LICENSE-2.0
7 : *
8 : * SPDX-License-Identifier: Apache-2.0
9 : ********************************************************************************/
10 : #pragma once
11 :
12 : #include <etl/delegate.h>
13 : #include <etl/expected.h>
14 :
15 : #include "Logger.h"
16 : #include "middleware/core/Future.h"
17 : #include "org/test/foo/FooProxy.h"
18 :
19 : /**
20 : * FooProxy wrapper for the simulation Cluster1 consumer.
21 : *
22 : * Registers a change-notification callback on the fooDefault attribute and
23 : * provides an asynchronous getter and application-level polling for FooMethod.
24 : * All operations, including middleware processing, run on the consumer thread.
25 : *
26 : * \tparam CLUSTER_ID The ClusterId of the cluster this proxy lives on.
27 : */
28 : template<::middleware::core::ClusterId CLUSTER_ID>
29 : class FooProxyWrapper
30 : {
31 : public:
32 : using FooMethodResult = org::test::foo::Foo::FooMethodResult;
33 : using FooMethodState = ::middleware::core::Future::State;
34 :
35 : struct FooMethodPollResult
36 : {
37 : FooMethodState state;
38 : FooMethodResult value;
39 : };
40 :
41 13 : void init()
42 : {
43 : using namespace org::test::foo::Foo;
44 :
45 13 : proxy_.init(internal::InstanceId::InstanceId_1, CLUSTER_ID);
46 :
47 13 : proxy_.fooDefault.setReceiveHandler(
48 : ::etl::delegate<void(FooStruct const&)>::
49 : create<FooProxyWrapper, &FooProxyWrapper::onFooDefaultChanged>(*this));
50 13 : }
51 :
52 14 : void deInit()
53 : {
54 14 : proxy_.deInit();
55 14 : fooMethodState_ = FooMethodState::Invalid;
56 14 : fooMethodValue_ = {};
57 14 : }
58 :
59 25 : [[nodiscard]] ::middleware::core::HRESULT requestFooMethod(uint32_t const startValue)
60 : {
61 : using ::middleware::core::HRESULT;
62 25 : if (fooMethodState_ != FooMethodState::Invalid)
63 : {
64 4 : simulation::Logger::log(
65 : static_cast<uint8_t>(CLUSTER_ID), "FooMethod request rejected: Busy");
66 4 : return HRESULT::ServiceBusy;
67 : }
68 :
69 : using Proxy = org::test::foo::Foo::proxy::FooProxy;
70 : auto const cb = Proxy::FooMethodCallback::
71 21 : template create<FooProxyWrapper, &FooProxyWrapper::onFooMethodResponse>(*this);
72 :
73 21 : fooMethodState_ = FooMethodState::Pending;
74 21 : auto const request = proxy_.fooMethod(startValue, cb);
75 21 : if (!request.has_value())
76 : {
77 2 : fooMethodState_ = FooMethodState::Invalid;
78 2 : simulation::Logger::log(
79 : static_cast<uint8_t>(CLUSTER_ID),
80 : "FooMethod request failed, error=",
81 2 : static_cast<unsigned>(request.error()));
82 2 : return request.error();
83 : }
84 :
85 19 : simulation::Logger::log(
86 : static_cast<uint8_t>(CLUSTER_ID), "FooMethod request sent, startValue=", startValue);
87 19 : return HRESULT::Ok;
88 : }
89 :
90 43 : [[nodiscard]] FooMethodPollResult pollFooMethod()
91 : {
92 43 : FooMethodPollResult const result{fooMethodState_, fooMethodValue_};
93 43 : if (fooMethodState_ != FooMethodState::Invalid
94 21 : && fooMethodState_ != FooMethodState::Pending)
95 : {
96 17 : fooMethodState_ = FooMethodState::Invalid;
97 17 : fooMethodValue_ = {};
98 : }
99 43 : return result;
100 : }
101 :
102 21 : void requestGet()
103 : {
104 : using namespace org::test::foo::Foo;
105 :
106 : using GetterCb = ::etl::delegate<void(::etl::expected<
107 : ::etl::reference_wrapper<FooStruct const>,
108 : ::middleware::core::Future::State> const&)>;
109 :
110 21 : auto const cb = GetterCb::create<FooProxyWrapper, &FooProxyWrapper::onGetResponse>(*this);
111 :
112 21 : (void)proxy_.fooDefault.get(cb);
113 21 : }
114 :
115 : private:
116 18 : void onFooMethodResponse(org::test::foo::Foo::proxy::FooProxy::FooMethodResult const& result)
117 : {
118 18 : if (result.has_value())
119 : {
120 : // The middleware releases the response payload after this callback.
121 15 : fooMethodValue_ = result.value().get();
122 15 : fooMethodState_ = FooMethodState::Ready;
123 : }
124 : else
125 : {
126 3 : fooMethodState_ = result.error();
127 : }
128 18 : }
129 :
130 20 : void onFooDefaultChanged(org::test::foo::Foo::FooStruct const& value)
131 : {
132 20 : simulation::Logger::log(
133 20 : static_cast<uint8_t>(CLUSTER_ID), "Foo attribute changed, fooValue=", value.fooValue);
134 20 : }
135 :
136 21 : void onGetResponse(::etl::expected<
137 : ::etl::reference_wrapper<org::test::foo::Foo::FooStruct const>,
138 : ::middleware::core::Future::State> const& result)
139 : {
140 21 : if (result.has_value())
141 : {
142 21 : simulation::Logger::log(
143 : static_cast<uint8_t>(CLUSTER_ID),
144 : "Foo get response, fooValue=",
145 21 : result.value().get().fooValue);
146 : }
147 21 : }
148 :
149 : org::test::foo::Foo::proxy::FooProxy proxy_;
150 : FooMethodState fooMethodState_{FooMethodState::Invalid};
151 : FooMethodResult fooMethodValue_{};
152 : };
|