1 /*!
2 * \copyright Copyright (c) 2015-2021 Governikus GmbH & Co. KG, Germany
3 */
4
5 #include "ReaderManagerWorker.h"
6
7 #include "Initializer.h"
8 #include "Reader.h"
9
10 #include <QLoggingCategory>
11 #include <QPluginLoader>
12 #include <QThread>
13
14 Q_DECLARE_LOGGING_CATEGORY(card)
15
16 using namespace governikus;
17
__anon1f26c66a0102null18 INIT_FUNCTION([] {
19 qRegisterMetaType<QSharedPointer<CardConnectionWorker> >("QSharedPointer<CardConnectionWorker>");
20 })
21
22
ReaderManagerWorker()23 ReaderManagerWorker::ReaderManagerWorker()
24 : QObject()
25 , mPlugIns()
26 {
27 }
28
29
~ReaderManagerWorker()30 ReaderManagerWorker::~ReaderManagerWorker()
31 {
32 Q_ASSERT(QObject::thread() == QThread::currentThread());
33 qCDebug(card) << "Worker removed";
34 }
35
36
shutdown()37 void ReaderManagerWorker::shutdown()
38 {
39 qCDebug(card) << "Shutdown ReaderManagerWorker";
40 for (auto& plugin : qAsConst(mPlugIns))
41 {
42 plugin->stopScan();
43
44 qCDebug(card) << "Shutdown plugin:" << plugin->metaObject()->className();
45 plugin->shutdown();
46
47 // Plugins and therefore their members are not auto destructed due to a bug in Qt.
48 // https://bugreports.qt.io/browse/QTBUG-17458
49 plugin->deleteLater();
50 }
51 mPlugIns.clear();
52 }
53
54
onThreadStarted()55 void ReaderManagerWorker::onThreadStarted()
56 {
57 Q_ASSERT(QObject::thread() == QThread::currentThread());
58
59 qCDebug(card) << "Thread started";
60 registerPlugIns();
61
62 Q_EMIT fireInitialized();
63 }
64
65
registerPlugIns()66 void ReaderManagerWorker::registerPlugIns()
67 {
68 qCDebug(card) << "Try to register plugins";
69 const auto& plugins = QPluginLoader::staticPlugins();
70 for (const auto& plugin : plugins)
71 {
72 if (isPlugIn(plugin.metaData()))
73 {
74 qCDebug(card) << "Register and initialize plugin:" << plugin.metaData();
75 ReaderManagerPlugIn* pluginInstance = qobject_cast<ReaderManagerPlugIn*>(plugin.instance());
76 if (pluginInstance == nullptr)
77 {
78 qCWarning(card) << "Cannot cast to plugin instance:" << plugin.instance();
79 }
80 else
81 {
82 registerPlugIn(pluginInstance);
83 pluginInstance->init();
84
85 Q_EMIT firePluginAdded(pluginInstance->getInfo());
86 }
87 }
88 }
89 }
90
91
isPlugIn(const QJsonObject & pJson) const92 bool ReaderManagerWorker::isPlugIn(const QJsonObject& pJson) const
93 {
94 return pJson.value(QStringLiteral("IID")).toString() == QLatin1String("governikus.ReaderManagerPlugIn");
95 }
96
97
registerPlugIn(ReaderManagerPlugIn * pPlugIn)98 void ReaderManagerWorker::registerPlugIn(ReaderManagerPlugIn* pPlugIn)
99 {
100 Q_ASSERT(pPlugIn != nullptr);
101 Q_ASSERT(!mPlugIns.contains(pPlugIn));
102
103 mPlugIns << pPlugIn;
104
105 connect(pPlugIn, &ReaderManagerPlugIn::fireReaderAdded, this, &ReaderManagerWorker::fireReaderAdded);
106 connect(pPlugIn, &ReaderManagerPlugIn::fireReaderRemoved, this, &ReaderManagerWorker::fireReaderRemoved);
107 connect(pPlugIn, &ReaderManagerPlugIn::fireReaderPropertiesUpdated, this, &ReaderManagerWorker::fireReaderPropertiesUpdated);
108 connect(pPlugIn, &ReaderManagerPlugIn::fireStatusChanged, this, &ReaderManagerWorker::fireStatusChanged);
109 connect(pPlugIn, &ReaderManagerPlugIn::fireCardInserted, this, &ReaderManagerWorker::fireCardInserted);
110 connect(pPlugIn, &ReaderManagerPlugIn::fireCardRemoved, this, &ReaderManagerWorker::fireCardRemoved);
111 connect(pPlugIn, &ReaderManagerPlugIn::fireCardRetryCounterChanged, this, &ReaderManagerWorker::fireCardRetryCounterChanged);
112 }
113
114
reset(ReaderManagerPlugInType pType)115 void ReaderManagerWorker::reset(ReaderManagerPlugInType pType)
116 {
117 Q_ASSERT(QObject::thread() == QThread::currentThread());
118
119 for (auto& plugin : qAsConst(mPlugIns))
120 {
121 if (plugin->getInfo().getPlugInType() == pType)
122 {
123 qCDebug(card) << "Reset plugin:" << plugin->metaObject()->className();
124 plugin->reset();
125 }
126 }
127 }
128
129
startScan(ReaderManagerPlugInType pType,bool pAutoConnect)130 void ReaderManagerWorker::startScan(ReaderManagerPlugInType pType, bool pAutoConnect)
131 {
132 Q_ASSERT(QObject::thread() == QThread::currentThread());
133
134 for (auto& plugin : qAsConst(mPlugIns))
135 {
136 if (plugin->getInfo().getPlugInType() == pType)
137 {
138 qCDebug(card) << "Start scan on plugin:" << plugin->metaObject()->className();
139 plugin->startScan(pAutoConnect);
140 }
141 }
142 }
143
144
stopScan(ReaderManagerPlugInType pType,const QString & pError)145 void ReaderManagerWorker::stopScan(ReaderManagerPlugInType pType, const QString& pError)
146 {
147 Q_ASSERT(QObject::thread() == QThread::currentThread());
148
149 for (auto& plugin : qAsConst(mPlugIns))
150 {
151 if (plugin->getInfo().getPlugInType() == pType)
152 {
153 qCDebug(card) << "Stop scan on plugin:" << plugin->metaObject()->className();
154 plugin->stopScan(pError);
155 }
156 }
157 }
158
159
isScanRunning() const160 bool ReaderManagerWorker::isScanRunning() const
161 {
162 Q_ASSERT(QObject::thread() == QThread::currentThread());
163
164 for (const auto& plugin : qAsConst(mPlugIns))
165 {
166 if (plugin->isScanRunning())
167 {
168 return true;
169 }
170 }
171 return false;
172 }
173
174
isScanRunning(ReaderManagerPlugInType pType) const175 bool ReaderManagerWorker::isScanRunning(ReaderManagerPlugInType pType) const
176 {
177 Q_ASSERT(QObject::thread() == QThread::currentThread());
178
179 for (const auto& plugin : qAsConst(mPlugIns))
180 {
181 if (plugin->getInfo().getPlugInType() == pType && plugin->isScanRunning())
182 {
183 return true;
184 }
185 }
186 return false;
187 }
188
189
getReaderInfos() const190 QVector<ReaderInfo> ReaderManagerWorker::getReaderInfos() const
191 {
192 Q_ASSERT(QObject::thread() == QThread::currentThread());
193
194 QVector<ReaderInfo> list;
195 for (const auto& plugIn : qAsConst(mPlugIns))
196 {
197 const auto& readerList = plugIn->getReaders();
198 for (const Reader* const reader : readerList)
199 {
200 list += reader->getReaderInfo();
201 }
202 }
203 return list;
204 }
205
206
updateReaderInfo(const QString & pReaderName)207 void ReaderManagerWorker::updateReaderInfo(const QString& pReaderName)
208 {
209 Q_ASSERT(QObject::thread() == QThread::currentThread());
210
211 Reader* reader = getReader(pReaderName);
212 if (reader == nullptr)
213 {
214 qCWarning(card) << "Requested reader does not exist:" << pReaderName;
215 return;
216 }
217 reader->update();
218 }
219
220
getReader(const QString & pReaderName) const221 Reader* ReaderManagerWorker::getReader(const QString& pReaderName) const
222 {
223 Q_ASSERT(QObject::thread() == QThread::currentThread());
224
225 for (auto& plugin : qAsConst(mPlugIns))
226 {
227 const auto& readerList = plugin->getReaders();
228 for (Reader* reader : readerList)
229 {
230 if (reader->getName() == pReaderName)
231 {
232 return reader;
233 }
234 }
235 }
236
237 qCWarning(card) << "Requested reader does not exist:" << pReaderName;
238 return nullptr;
239 }
240
241
createCardConnectionWorker(const QString & pReaderName)242 void ReaderManagerWorker::createCardConnectionWorker(const QString& pReaderName)
243 {
244 Q_ASSERT(QObject::thread() == QThread::currentThread());
245
246 QSharedPointer<CardConnectionWorker> worker;
247 if (auto reader = getReader(pReaderName))
248 {
249 worker = reader->createCardConnectionWorker();
250 }
251 Q_EMIT fireCardConnectionWorkerCreated(worker);
252 }
253
254
updateRetryCounters()255 void ReaderManagerWorker::updateRetryCounters()
256 {
257 Q_ASSERT(QObject::thread() == QThread::currentThread());
258
259 const auto& readerInfos = getReaderInfos();
260 for (const auto& readerInfo : readerInfos)
261 {
262 QSharedPointer<CardConnectionWorker> worker;
263 if (const auto& reader = getReader(readerInfo.getName()))
264 {
265 worker = reader->createCardConnectionWorker();
266 if (worker)
267 {
268 worker->updateRetryCounter();
269 }
270 }
271 }
272 }
273