ifw-slm 0.1.2
 
Loading...
Searching...
No Matches
actionsLoopClose.hpp
Go to the documentation of this file.
1
17
18#ifndef IFWSLM_ACTIONS_LOOP_CLOSE_HPP
19#define IFWSLM_ACTIONS_LOOP_CLOSE_HPP
20
21#include "baseLoopActions.hpp"
22#include "dataContext.hpp"
23#include "logger.hpp"
24#include "cmdsImpl.hpp" // includes events.rad.hpp
25
26#include <rad/application.hpp>
27#include <rad/smAdapter.hpp>
28#include <rad/timer.hpp>
29#include <rad/smEvent.hpp>
30
31#include <boost/asio.hpp>
32
33#include <string>
34#include <memory>
35
36namespace ifw::slm {
37template<int LOOP_INDEX>
38void CreateCloseLoopTimer(boost::asio::io_context& ios, rad::SMAdapter& sm, std::unique_ptr<rad::Timer>& timer, int period_sec);
39
40// Helper function to create the appropriate trigger event based on loop index
41inline rad::UniqueEvent MakeTriggerEvent(int loop_index) {
42 switch (loop_index) {
43 case 1: return rad::UniqueEvent(new Events::Trigger1());
44 case 2: return rad::UniqueEvent(new Events::Trigger2());
45 case 3: return rad::UniqueEvent(new Events::Trigger3());
46 case 4: return rad::UniqueEvent(new Events::Trigger4());
47 case 5: return rad::UniqueEvent(new Events::Trigger5());
48 case 6: return rad::UniqueEvent(new Events::Trigger6());
49 case 7: return rad::UniqueEvent(new Events::Trigger7());
50 case 8: return rad::UniqueEvent(new Events::Trigger8());
51 case 9: return rad::UniqueEvent(new Events::Trigger9());
52 default: throw std::out_of_range("Invalid loop index: " + std::to_string(loop_index));
53 }
54}
55
62template<int LOOP_INDEX>
64public:
66
75 ActionsLoopClose(const std::string& name,
76 rad::Application& appl,
77 rad::ConfigurableActionMgr& action_mgr,
78 DataContext& data,
79 int loop_index,
80 std::shared_ptr<LoopCompletionHandler> completion_handler)
81 : base_type(name, appl, action_mgr, data, loop_index, completion_handler),
82 m_ios(appl.GetEventLoop()),
83 m_sm(appl),
84 m_timer_period_sec(CONFIG_DEFAULT_LOOP_PERIOD_SEC) {
85 RAD_TRACE(GetLogger());
86 ReadTimerPeriodFromConfig();
87 LOG4CPLUS_INFO(GetLogger(),
88 "Creating ActionsLoop" << LOOP_INDEX << "CloseLoop with timer period " << m_timer_period_sec << " s");
89 CreateCloseLoopTimer<LOOP_INDEX>(m_ios, m_sm, m_timer, m_timer_period_sec);
90 LOG4CPLUS_INFO(GetLogger(),
91 "Created timer for loop " << LOOP_INDEX << ": " << (m_timer ? "success" : "null"));
92 }
93
94 ~ActionsLoopClose() override {
95 RAD_TRACE(GetLogger());
96 // Timer is cleaned up by unique_ptr
97 }
98
99 void Configure(const std::vector<std::string>& keys) override {
100 RAD_TRACE(GetLogger());
102 ReadTimerPeriodFromConfig();
103 }
104
105 void Execute(scxml4cpp::Context* c) override {
106 RAD_TRACE(GetLogger());
107
108 LOG4CPLUS_DEBUG(GetLogger(),
109 "Loop " << LOOP_INDEX << " entering CloseLoop, installing timer (period=" << m_timer_period_sec << "s)");
110
111 // Reset consecutive failure counter on entering CloseLoop
112 m_loop_state.SetFail(false);
113 LOG4CPLUS_DEBUG(GetLogger(),
114 "Loop " << LOOP_INDEX << " reset consecutive failure counter");
115
116 // Call base class to update OLDB state (active=true, state=SL_CLOSED, cycle_start, etc.)
118
119 // Install the timer with the configured period
120 if (m_timer) {
121 m_timer->Install(m_timer_period_sec * 1000);
122 }
123 }
124
125 void Complete(scxml4cpp::Context* c) override {
126 RAD_TRACE(GetLogger());
127
128 // Call base class to update OLDB state (cycle_failure=false)
130
131 // Reinstall the timer for the next cycle
132 if (m_timer) {
133 m_timer->Install(m_timer_period_sec * 1000);
134 }
135 }
136
137 void Abort(scxml4cpp::Context* c) override {
138 RAD_TRACE(GetLogger());
139
140 LOG4CPLUS_DEBUG(GetLogger(),
141 "Loop " << LOOP_INDEX << " exiting CloseLoop, cancelling timer");
142
143 // Call base class to update OLDB state (cycle_failure=true)
145
146 // Cancel the timer to stop execution
147 if (m_timer) {
148 m_timer->Cancel();
149 }
150 }
151
152 void CycleError(scxml4cpp::Context* c) override {
153 RAD_TRACE(GetLogger());
154
155 LOG4CPLUS_DEBUG(GetLogger(),
156 "Loop " << LOOP_INDEX << " CycleError - GenCmd" << LOOP_INDEX << "_Err: timer reinstalled for retry");
157
158 // Read max_errors from configuration (fallback to 3)
159 int max_errors = 3;
160 try {
161 max_errors = m_data.GetConfig().GetParam<int>(
162 GetLoopConfigKey(m_loop_index, "max_errors"));
163 } catch (const std::exception& e) {
164 LOG4CPLUS_DEBUG(GetLogger(),
165 "Loop " << LOOP_INDEX << " max_errors not configured, using default: " << max_errors);
166 }
167
168 // Call base class to update OLDB and check consecutive failures
170
171 // If not auto-opening (counter < max_errors), reinstall timer for retry
172 if (!m_loop_state.CheckStop(max_errors)) {
173 LOG4CPLUS_DEBUG(GetLogger(),
174 "Loop " << LOOP_INDEX << " reinstalling timer for retry (period=" << m_timer_period_sec << "s)");
175 if (m_timer) {
176 m_timer->Cancel();
177 m_timer->Install(m_timer_period_sec * 1000);
178 }
179 }
180 }
181
182 void InstallTimer(scxml4cpp::Context* c) override {
183 RAD_TRACE(GetLogger());
184
185 LOG4CPLUS_DEBUG(GetLogger(),
186 "Loop " << LOOP_INDEX << " reinstalling timer for next cycle (period=" << m_timer_period_sec << "s)");
187
188 // Reset failure counter on successful cycle completion
189 m_loop_state.SetFail(false);
190
191 // Reinstall the timer for the next cycle
192 if (m_timer) {
193 m_timer->Install(m_timer_period_sec * 1000);
194 }
195 }
196
199
200private:
201 boost::asio::io_context& m_ios;
202 rad::SMAdapter& m_sm;
203 std::unique_ptr<rad::Timer> m_timer;
204 int m_timer_period_sec;
205
206 void ReadTimerPeriodFromConfig() {
207 try {
208 auto& config = m_data.GetConfig();
209 std::string config_key = GetLoopConfigKey(m_loop_index, "period_sec");
210 int new_period = config.GetParam<int>(config_key);
211 if (new_period != m_timer_period_sec) {
212 m_timer_period_sec = new_period;
213 LOG4CPLUS_INFO(GetLogger(),
214 "Loop " << m_loop_index << " timer period updated to " << m_timer_period_sec << " s (key=" << config_key << ")");
215 }
216 } catch (const std::exception& e) {
217 LOG4CPLUS_INFO(GetLogger(),
218 "Loop " << m_loop_index << " timer period not configured (key=" << GetLoopConfigKey(m_loop_index, "period_sec") << "), using default: "
219 << m_timer_period_sec << " s");
220 }
221 }
222};
223
224// Template implementation using the helper function
225template<int LOOP_INDEX>
226inline void CreateCloseLoopTimer(boost::asio::io_context& ios, rad::SMAdapter& sm, std::unique_ptr<rad::Timer>& timer, int /*period_sec*/) {
227 RAD_TRACE(GetLogger());
228 timer = std::make_unique<rad::Timer>(ios, sm, MakeTriggerEvent(LOOP_INDEX));
229}
230
231
232
233// ===== Type aliases for the 9 loop CloseLoop action classes =====
234
244
245} // namespace ifw::slm
246
247#endif // IFWSLM_ACTIONS_LOOP_CLOSE_HPP
Base action classes for loop control actions.
Definition actionsLoopClose.hpp:63
void Abort(scxml4cpp::Context *c) override
Definition actionsLoopClose.hpp:137
~ActionsLoopClose() override
Definition actionsLoopClose.hpp:94
BaseLoopCloseActions base_type
Definition actionsLoopClose.hpp:65
void Execute(scxml4cpp::Context *c) override
Definition actionsLoopClose.hpp:105
void Configure(const std::vector< std::string > &keys) override
Definition actionsLoopClose.hpp:99
ActionsLoopClose(const std::string &name, rad::Application &appl, rad::ConfigurableActionMgr &action_mgr, DataContext &data, int loop_index, std::shared_ptr< LoopCompletionHandler > completion_handler)
Definition actionsLoopClose.hpp:75
ActionsLoopClose & operator=(const ActionsLoopClose &)=delete
void InstallTimer(scxml4cpp::Context *c) override
Definition actionsLoopClose.hpp:182
ActionsLoopClose(const ActionsLoopClose &)=delete
void CycleError(scxml4cpp::Context *c) override
Definition actionsLoopClose.hpp:152
void Complete(scxml4cpp::Context *c) override
Definition actionsLoopClose.hpp:125
BaseLoopCloseActions(const std::string &name, rad::Application &appl, rad::ConfigurableActionMgr &action_mgr, DataContext &data, int loop_index, std::shared_ptr< LoopCompletionHandler > completion_handler=nullptr)
Definition baseLoopActions.cpp:185
virtual void CycleError(scxml4cpp::Context *c)
Definition baseLoopActions.cpp:265
int m_loop_index
Definition baseLoopActions.hpp:339
virtual void Complete(scxml4cpp::Context *c)
Definition baseLoopActions.cpp:215
virtual void Abort(scxml4cpp::Context *c)
Definition baseLoopActions.cpp:222
void Configure(const std::vector< std::string > &keys) override
Definition baseLoopActions.cpp:205
LoopStateData m_loop_state
Definition baseLoopActions.hpp:341
DataContext & m_data
Definition baseLoopActions.hpp:338
virtual void Execute(scxml4cpp::Context *c)
Definition baseLoopActions.cpp:209
Definition dataContext.hpp:29
DataContext class header file.
Default logger name.
Definition actionMgr.cpp:29
ActionsLoopClose< 3 > ActionsLoop3CloseLoop
Definition actionsLoopClose.hpp:237
ActionsLoopClose< 8 > ActionsLoop8CloseLoop
Definition actionsLoopClose.hpp:242
ActionsLoopClose< 5 > ActionsLoop5CloseLoop
Definition actionsLoopClose.hpp:239
ActionsLoopClose< 4 > ActionsLoop4CloseLoop
Definition actionsLoopClose.hpp:238
ActionsLoopClose< 7 > ActionsLoop7CloseLoop
Definition actionsLoopClose.hpp:241
ActionsLoopClose< 2 > ActionsLoop2CloseLoop
Definition actionsLoopClose.hpp:236
rad::UniqueEvent MakeTriggerEvent(int loop_index)
Definition actionsLoopClose.hpp:41
void CreateCloseLoopTimer(boost::asio::io_context &ios, rad::SMAdapter &sm, std::unique_ptr< rad::Timer > &timer, int period_sec)
Definition actionsLoopClose.hpp:226
log4cplus::Logger & GetLogger()
Definition logger.cpp:14
std::string GetLoopConfigKey(int loop_index, const std::string &param_name)
Definition slConfig.cpp:26
ActionsLoopClose< 1 > ActionsLoop1CloseLoop
Definition actionsLoopClose.hpp:235
ActionsLoopClose< 9 > ActionsLoop9CloseLoop
Definition actionsLoopClose.hpp:243
const int CONFIG_DEFAULT_LOOP_PERIOD_SEC
Definition config.hpp:34
ActionsLoopClose< 6 > ActionsLoop6CloseLoop
Definition actionsLoopClose.hpp:240