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