Keyple Service C++ Library - 3.4.1
Component of the Keyple C++ middleware
ObservableReaderStateServiceAdapter.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional *
5 * information regarding copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the *
8 * terms of the Eclipse Public License 2.0 which is available at *
9 * http://www.eclipse.org/legal/epl-2.0 *
10 * *
11 * SPDX-License-Identifier: EPL-2.0 *
12 ******************************************************************************/
13
14#include "keyple/core/service/ObservableReaderStateServiceAdapter.hpp"
15
16#include <memory>
17#include <string>
18
19#include "keyple/core/plugin/spi/reader/observable/state/insertion/CardInsertionWaiterAsynchronousSpi.hpp"
20#include "keyple/core/plugin/spi/reader/observable/state/insertion/CardInsertionWaiterBlockingSpi.hpp"
21#include "keyple/core/plugin/spi/reader/observable/state/insertion/CardInsertionWaiterNonBlockingSpi.hpp"
22#include "keyple/core/plugin/spi/reader/observable/state/insertion/WaitForCardInsertionBlockingSpi.hpp"
23#include "keyple/core/plugin/spi/reader/observable/state/insertion/WaitForCardInsertionNonBlockingSpi.hpp"
24#include "keyple/core/plugin/spi/reader/observable/state/processing/CardPresenceMonitorBlockingSpi.hpp"
25#include "keyple/core/plugin/spi/reader/observable/state/processing/WaitForCardRemovalDuringProcessingBlockingSpi.hpp"
26#include "keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterBlockingSpi.hpp"
27#include "keyple/core/plugin/spi/reader/observable/state/removal/CardRemovalWaiterNonBlockingSpi.hpp"
28#include "keyple/core/plugin/spi/reader/observable/state/removal/WaitForCardRemovalNonBlockingSpi.hpp"
29#include "keyple/core/service/CardInsertionActiveMonitoringJobAdapter.hpp"
30#include "keyple/core/service/CardInsertionPassiveMonitoringJobAdapter.hpp"
31#include "keyple/core/service/CardRemovalActiveMonitoringJobAdapter.hpp"
32#include "keyple/core/service/CardRemovalPassiveMonitoringJobAdapter.hpp"
33#include "keyple/core/service/WaitForCardInsertionStateAdapter.hpp"
34#include "keyple/core/service/WaitForCardProcessingStateAdapter.hpp"
35#include "keyple/core/service/WaitForCardRemovalStateAdapter.hpp"
36#include "keyple/core/service/WaitForStartDetectStateAdapter.hpp"
37
38namespace keyple {
39namespace core {
40namespace service {
41
42using keyple::core::plugin::spi::reader::observable::state::insertion::
43 CardInsertionWaiterAsynchronousSpi;
44using keyple::core::plugin::spi::reader::observable::state::insertion::
45 CardInsertionWaiterBlockingSpi;
46using keyple::core::plugin::spi::reader::observable::state::insertion::
47 CardInsertionWaiterNonBlockingSpi;
48using keyple::core::plugin::spi::reader::observable::state::insertion::
49 WaitForCardInsertionBlockingSpi;
50using keyple::core::plugin::spi::reader::observable::state::insertion::
51 WaitForCardInsertionNonBlockingSpi;
52using keyple::core::plugin::spi::reader::observable::state::processing::
53 CardPresenceMonitorBlockingSpi;
54using keyple::core::plugin::spi::reader::observable::state::processing::
55 WaitForCardRemovalDuringProcessingBlockingSpi;
56using keyple::core::plugin::spi::reader::observable::state::removal::
57 CardRemovalWaiterBlockingSpi;
58using keyple::core::plugin::spi::reader::observable::state::removal::
59 CardRemovalWaiterNonBlockingSpi;
60using keyple::core::plugin::spi::reader::observable::state::removal::
61 WaitForCardRemovalNonBlockingSpi;
62
63ObservableReaderStateServiceAdapter::ObservableReaderStateServiceAdapter(
64 ObservableLocalReaderAdapter* reader)
65: mReader(reader)
66, mReaderSpi(reader->getObservableReaderSpi())
67, mExecutorService(std::make_shared<ExecutorService>())
68{
69 /* Wait for start */
70 mStates.insert(
71 {MonitoringState::WAIT_FOR_START_DETECTION,
72 std::make_shared<WaitForStartDetectStateAdapter>(mReader)});
73
74 /* Insertion */
75 if (std::dynamic_pointer_cast<CardInsertionWaiterAsynchronousSpi>(
76 mReaderSpi)
77 || std::dynamic_pointer_cast<WaitForCardInsertionAutonomousSpi>(
78 mReaderSpi)) {
79 mStates.insert(
80 {MonitoringState::WAIT_FOR_CARD_INSERTION,
81 std::make_shared<WaitForCardInsertionStateAdapter>(mReader)});
82
83 } else if (
84 std::dynamic_pointer_cast<CardInsertionWaiterNonBlockingSpi>(mReaderSpi)
85 || std::dynamic_pointer_cast<WaitForCardInsertionNonBlockingSpi>(
86 mReaderSpi)) {
87 const auto readerSpi
88 = std::dynamic_pointer_cast<CardInsertionWaiterNonBlockingSpi>(
89 mReaderSpi);
90 int sleepDurationMillis
91 = readerSpi ? readerSpi->getCardInsertionMonitoringSleepDuration()
92 : 100;
93
94 auto cardInsertionActiveMonitoringJobAdapter
95 = std::make_shared<CardInsertionActiveMonitoringJobAdapter>(
96 mReader, sleepDurationMillis, true);
97
98 mStates.insert(
99 {MonitoringState::WAIT_FOR_CARD_INSERTION,
100 std::make_shared<WaitForCardInsertionStateAdapter>(
101 mReader,
102 cardInsertionActiveMonitoringJobAdapter,
103 mExecutorService)});
104
105 } else if (
106 std::dynamic_pointer_cast<CardInsertionWaiterBlockingSpi>(mReaderSpi)
107 || std::dynamic_pointer_cast<WaitForCardInsertionBlockingSpi>(
108 mReaderSpi)) {
109 auto cardInsertionPassiveMonitoringJobAdapter
110 = std::make_shared<CardInsertionPassiveMonitoringJobAdapter>(
111 mReader);
112 mStates.insert(
113 {MonitoringState::WAIT_FOR_CARD_INSERTION,
114 std::make_shared<WaitForCardInsertionStateAdapter>(
115 mReader,
116 cardInsertionPassiveMonitoringJobAdapter,
117 mExecutorService)});
118
119 } else {
120 throw IllegalStateException(
121 std::string(
122 "Cannot cast the provided reader extension to a valid "
123 "WaitForCardInsertion interface. Actual type: ")
124 + typeid(mReaderSpi).name());
125 }
126
127 /* Processing */
128 if (std::dynamic_pointer_cast<CardPresenceMonitorBlockingSpi>(mReaderSpi)
129 || std::dynamic_pointer_cast<
130 WaitForCardRemovalDuringProcessingBlockingSpi>(mReaderSpi)) {
131 auto cardRemovalPassiveMonitoringJobAdapter
132 = std::make_shared<CardRemovalPassiveMonitoringJobAdapter>(mReader);
133 mStates.insert(
134 {MonitoringState::WAIT_FOR_CARD_PROCESSING,
135 std::make_shared<WaitForCardProcessingStateAdapter>(
136 mReader,
137 cardRemovalPassiveMonitoringJobAdapter,
138 mExecutorService)});
139
140 } else {
141 mStates.insert(
142 {MonitoringState::WAIT_FOR_CARD_PROCESSING,
143 std::make_shared<WaitForCardProcessingStateAdapter>(mReader)});
144 }
145
146 /* Removal */
147 if (std::dynamic_pointer_cast<CardRemovalWaiterAsynchronousSpi>(mReaderSpi)
148 || std::dynamic_pointer_cast<WaitForCardRemovalAutonomousSpi>(
149 mReaderSpi)) {
150 mStates.insert(
151 {MonitoringState::WAIT_FOR_CARD_REMOVAL,
152 std::make_shared<WaitForCardRemovalStateAdapter>(mReader)});
153
154 } else if (
155 std::dynamic_pointer_cast<CardRemovalWaiterNonBlockingSpi>(mReaderSpi)
156 || std::dynamic_pointer_cast<WaitForCardRemovalNonBlockingSpi>(
157 mReaderSpi)) {
158 const auto readerSpi
159 = std::dynamic_pointer_cast<CardRemovalWaiterNonBlockingSpi>(
160 mReaderSpi);
161 int sleepDurationMillis
162 = readerSpi ? readerSpi->getCardRemovalMonitoringSleepDuration()
163 : 100;
164
165 auto cardRemovalActiveMonitoringJobAdapter
166 = std::make_shared<CardRemovalActiveMonitoringJobAdapter>(
167 mReader, sleepDurationMillis);
168
169 mStates.insert(
170 {MonitoringState::WAIT_FOR_CARD_REMOVAL,
171 std::make_shared<WaitForCardRemovalStateAdapter>(
172 mReader,
173 cardRemovalActiveMonitoringJobAdapter,
174 mExecutorService)});
175
176 } else if (
177 std::dynamic_pointer_cast<CardRemovalWaiterBlockingSpi>(mReaderSpi)
178 || std::dynamic_pointer_cast<WaitForCardRemovalBlockingSpi>(
179 mReaderSpi)) {
180 auto cardRemovalPassiveMonitoringJobAdapter
181 = std::make_shared<CardRemovalPassiveMonitoringJobAdapter>(mReader);
182 mStates.insert(
183 {MonitoringState::WAIT_FOR_CARD_REMOVAL,
184 std::make_shared<WaitForCardRemovalStateAdapter>(
185 mReader,
186 cardRemovalPassiveMonitoringJobAdapter,
187 mExecutorService)});
188
189 } else {
190 throw IllegalStateException(
191 std::string(
192 "Cannot cast the provided reader extension to a valid "
193 "WaitForCardRemoval interface. Actual type: ")
194 + typeid(mReaderSpi).name());
195 }
196
197 switchState(MonitoringState::WAIT_FOR_START_DETECTION);
198}
199
200void
201ObservableReaderStateServiceAdapter::onEvent(const InternalEvent event)
202{
203 /*
204 * C++: cannot use std::lock_guard as mutex needs to be unlocked before
205 * calling onEvent.
206 */
207 mMutex.lock();
208
209 switch (event) {
210 case InternalEvent::CARD_INSERTED:
211 case InternalEvent::CARD_REMOVED:
212 case InternalEvent::CARD_PROCESSED:
213 case InternalEvent::STOP_DETECT:
214 case InternalEvent::TIME_OUT:
215 break;
216 case InternalEvent::START_DETECT:
217 mReaderSpi->onStartDetection();
218 break;
219 }
220
221 mMutex.unlock();
222 mCurrentState->onEvent(event);
223}
224
225void
226ObservableReaderStateServiceAdapter::switchState(const MonitoringState stateId)
227{
228 std::lock_guard<std::mutex> lock(mMutex);
229
230 if (mCurrentState != nullptr) {
231 mLogger->trace(
232 "[fsmService=%] Switching state [from=%, to=%]\n",
233 mReader->getName(),
234 mCurrentState->getMonitoringState(),
235 stateId);
236 mCurrentState->onDeactivate();
237 } else {
238 mLogger->trace(
239 "[fsmService=%] Switching state [from=null, to=%]\n",
240 mReader->getName(),
241 stateId);
242 }
243
244 /* Switch currentState */
245 mCurrentState = mStates.at(stateId);
246
247 /*
248 * As soon as the state machine returns to the WAIT_FOR_START_DETECTION
249 * state, we deactivate card detection in the plugin.
250 */
251 if (stateId == MonitoringState::WAIT_FOR_START_DETECTION) {
252 mReaderSpi->onStopDetection();
253 }
254
255 /* onActivate the new current state */
256 mCurrentState->onActivate();
257
258 mLogger->trace(
259 "[fsmService=%] State switched [current=%, expected=%]",
260 mReader->getName(),
261 mCurrentState->getMonitoringState(),
262 stateId);
263}
264
265std::shared_ptr<AbstractObservableStateAdapter>
266ObservableReaderStateServiceAdapter::getCurrentState()
267{
268 std::lock_guard<std::mutex> lock(mMutex);
269
270 return mCurrentState;
271}
272
273MonitoringState
274ObservableReaderStateServiceAdapter::getCurrentMonitoringState()
275{
276 std::lock_guard<std::mutex> lock(mMutex);
277
278 return mCurrentState->getMonitoringState();
279}
280
281void
282ObservableReaderStateServiceAdapter::shutdown()
283{
284 mExecutorService->shutdown();
285}
286
287} /* namespace service */
288} /* namespace core */
289} /* namespace keyple */
ObservableLocalReaderAdapter::InternalEvent InternalEvent