6#include <qndefnfctextrecord.h>
7#include <qndefnfcsmartposterrecord.h>
8#include <qndefnfcurirecord.h>
12Q_DECLARE_LOGGING_CATEGORY(QT_NFC_NEARD)
14using namespace QtNfcPrivate;
16QNearFieldTargetPrivateImpl::QNearFieldTargetPrivateImpl(QObject *parent, QDBusObjectPath interfacePath)
17 : QNearFieldTargetPrivate(parent),
18 m_tagPath(interfacePath),
19 m_readRequested(
false)
21 m_readErrorTimer.setSingleShot(
true);
22 m_recordPathsCollectedTimer.setSingleShot(
true);
23 m_delayedWriteTimer.setSingleShot(
true);
25 qCDebug(QT_NFC_NEARD) <<
"tag found at path" << interfacePath.path();
26 m_dbusProperties =
new OrgFreedesktopDBusPropertiesInterface(QStringLiteral(
"org.neard"),
27 interfacePath.path(), QDBusConnection::systemBus(),
this);
28 if (!m_dbusProperties->isValid()) {
29 qCWarning(QT_NFC_NEARD) <<
"Could not connect to dbus property interface at path"
30 << interfacePath.path();
34 QDBusPendingReply<QVariantMap> reply = m_dbusProperties->GetAll(QStringLiteral(
"org.neard.Tag"));
35 reply.waitForFinished();
36 if (reply.isError()) {
37 qCWarning(QT_NFC_NEARD) <<
"Could not get properties of org.neard.Tag dbus interface";
41 const QVariantMap props = reply.value();
42 const QString type = props.value(QStringLiteral(
"Type")).toString();
43 m_type = QNearFieldTarget::ProprietaryTag;
45 if (type == QStringLiteral(
"Type 1"))
46 m_type = QNearFieldTarget::NfcTagType1;
47 else if (type == QStringLiteral(
"Type 2"))
48 m_type = QNearFieldTarget::NfcTagType2;
49 else if (type == QStringLiteral(
"Type 3"))
50 m_type = QNearFieldTarget::NfcTagType3;
51 else if (type == QStringLiteral(
"Type 4"))
52 m_type = QNearFieldTarget::NfcTagType4;
54 qCDebug(QT_NFC_NEARD) <<
"tag type" << type;
56 m_uid = props.value(QStringLiteral(
"Uid")).toByteArray();
57 qCDebug(QT_NFC_NEARD) <<
"tag UID" << m_uid.toHex();
59 connect(&m_recordPathsCollectedTimer, &QTimer::timeout,
60 this, &QNearFieldTargetPrivateImpl::createNdefMessage);
61 connect(&m_readErrorTimer, &QTimer::timeout,
62 this, &QNearFieldTargetPrivateImpl::handleReadError);
63 connect(&m_delayedWriteTimer, &QTimer::timeout,
64 this, &QNearFieldTargetPrivateImpl::handleWriteRequest);
65 connect(NeardHelper::instance(), &NeardHelper::recordFound,
66 this, &QNearFieldTargetPrivateImpl::handleRecordFound);
69QNearFieldTargetPrivateImpl::~QNearFieldTargetPrivateImpl()
73bool QNearFieldTargetPrivateImpl::isValid()
75 return m_dbusProperties->isValid() && NeardHelper::instance()->dbusObjectManager()->isValid();
78QByteArray QNearFieldTargetPrivateImpl::uid()
const
83QNearFieldTarget::Type QNearFieldTargetPrivateImpl::type()
const
88QNearFieldTarget::AccessMethods QNearFieldTargetPrivateImpl::accessMethods()
const
90 return QNearFieldTarget::NdefAccess;
93bool QNearFieldTargetPrivateImpl::hasNdefMessage()
95 return !m_recordPaths.isEmpty();
98QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::readNdefMessages()
103 if (m_currentReadRequestId.isValid())
104 return m_currentReadRequestId;
106 QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(
new QNearFieldTarget::RequestIdPrivate());
108 m_currentReadRequestId = requestId;
113 m_readRequested =
true;
114 if (hasNdefMessage())
117 m_readErrorTimer.start(1000);
121 return QNearFieldTarget::RequestId();
125QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::sendCommand(
const QByteArray &command)
128 return QNearFieldTarget::RequestId();
131QNearFieldTarget::RequestId QNearFieldTargetPrivateImpl::writeNdefMessages(
const QList<QNdefMessage> &messages)
134 qWarning(
"QNearFieldTarget::WriteNdefMessages() disabled. See QTBUG-43802\n");
135 return QNearFieldTarget::RequestId();
139 if (m_currentWriteRequestId.isValid())
140 return m_currentWriteRequestId;
142 qCDebug(QT_NFC_NEARD) <<
"writing messages";
143 if (messages.isEmpty() || messages.first().isEmpty()) {
144 qCWarning(QT_NFC_NEARD) <<
"No record specified";
145 return QNearFieldTarget::RequestId();
147 if (messages.count() > 1 || messages.first().count() > 1) {
149 qCWarning(QT_NFC_NEARD) <<
"Writing of only one NDEF record and message is supported";
150 return QNearFieldTarget::RequestId();
152 QNdefRecord record = messages.first().first();
154 if (record.typeNameFormat() == QNdefRecord::NfcRtd) {
155 m_currentWriteRequestData.clear();
156 if (record.isRecordType<QNdefNfcUriRecord>()) {
157 m_currentWriteRequestData.insert(QStringLiteral(
"Type"), QStringLiteral(
"URI"));
158 QNdefNfcUriRecord uriRecord =
static_cast<QNdefNfcUriRecord>(record);
159 m_currentWriteRequestData.insert(QStringLiteral(
"URI"), uriRecord.uri().toString());
160 }
else if (record.isRecordType<QNdefNfcSmartPosterRecord>()) {
161 m_currentWriteRequestData.insert(QStringLiteral(
"Type"), QStringLiteral(
"SmartPoster"));
162 QNdefNfcSmartPosterRecord spRecord =
static_cast<QNdefNfcSmartPosterRecord>(record);
163 m_currentWriteRequestData.insert(QStringLiteral(
"URI"), spRecord.uri().toString());
165 }
else if (record.isRecordType<QNdefNfcTextRecord>()) {
166 m_currentWriteRequestData.insert(QStringLiteral(
"Type"), QStringLiteral(
"Text"));
167 QNdefNfcTextRecord textRecord =
static_cast<QNdefNfcTextRecord>(record);
168 m_currentWriteRequestData.insert(QStringLiteral(
"Representation"), textRecord.text());
169 m_currentWriteRequestData.insert(QStringLiteral(
"Encoding"),
170 textRecord.encoding() == QNdefNfcTextRecord::Utf8 ?
171 QStringLiteral(
"UTF-8") : QStringLiteral(
"UTF-16") );
172 m_currentWriteRequestData.insert(QStringLiteral(
"Language"), textRecord.locale());
174 qCWarning(QT_NFC_NEARD) <<
"Record type not supported for writing";
175 return QNearFieldTarget::RequestId();
178 m_currentWriteRequestId = QNearFieldTarget::RequestId(
new QNearFieldTarget::RequestIdPrivate());
180 m_delayedWriteTimer.start(100);
182 return m_currentWriteRequestId;
185 return QNearFieldTarget::RequestId();
188QNdefRecord QNearFieldTargetPrivateImpl::readRecord(
const QDBusObjectPath &path)
190 qCDebug(QT_NFC_NEARD) <<
"reading record for path" << path.path();
191 OrgFreedesktopDBusPropertiesInterface recordInterface(QStringLiteral(
"org.neard"), path.path(),
192 QDBusConnection::systemBus());
193 if (!recordInterface.isValid())
194 return QNdefRecord();
196 QDBusPendingReply<QVariantMap> reply = recordInterface.GetAll(QStringLiteral(
"org.neard.Record"));
197 reply.waitForFinished();
199 return QNdefRecord();
201 const QString &value = reply.value().value(QStringLiteral(
"Representation")).toString();
202 const QString &locale = reply.value().value(QStringLiteral(
"Language")).toString();
203 const QString &encoding = reply.value().value(QStringLiteral(
"Encoding")).toString();
204 const QString &uri = reply.value().value(QStringLiteral(
"URI")).toString();
209 const QString type = reply.value().value(QStringLiteral(
"Type")).toString();
210 if (type == QStringLiteral(
"Text")) {
211 QNdefNfcTextRecord textRecord;
212 textRecord.setText(value);
213 textRecord.setLocale(locale);
214 textRecord.setEncoding((encoding == QStringLiteral(
"UTF-8")) ? QNdefNfcTextRecord::Utf8
215 : QNdefNfcTextRecord::Utf16);
217 }
else if (type == QStringLiteral(
"SmartPoster")) {
218 QNdefNfcSmartPosterRecord spRecord;
219 if (!value.isEmpty()) {
220 spRecord.addTitle(value, locale, (encoding == QStringLiteral(
"UTF-8"))
221 ? QNdefNfcTextRecord::Utf8
222 : QNdefNfcTextRecord::Utf16);
226 spRecord.setUri(QUrl(uri));
228 const QString &action = reply.value().value(QStringLiteral(
"Action")).toString();
229 if (!action.isEmpty()) {
230 if (action == QStringLiteral(
"Do"))
231 spRecord.setAction(QNdefNfcSmartPosterRecord::DoAction);
232 else if (action == QStringLiteral(
"Save"))
233 spRecord.setAction(QNdefNfcSmartPosterRecord::SaveAction);
234 else if (action == QStringLiteral(
"Edit"))
235 spRecord.setAction(QNdefNfcSmartPosterRecord::EditAction);
238 if (reply.value().contains(QStringLiteral(
"Size"))) {
239 uint size = reply.value().value(QStringLiteral(
"Size")).toUInt();
240 spRecord.setSize(size);
243 const QString &mimeType = reply.value().value(QStringLiteral(
"MIMEType")).toString();
244 if (!mimeType.isEmpty()) {
245 spRecord.setTypeInfo(mimeType);
250 }
else if (type == QStringLiteral(
"URI")) {
251 QNdefNfcUriRecord uriRecord;
252 uriRecord.setUri(QUrl(uri));
254 }
else if (type == QStringLiteral(
"MIME")) {
256 }
else if (type == QStringLiteral(
"AAR")) {
260 return QNdefRecord();
263void QNearFieldTargetPrivateImpl::handleRecordFound(
const QDBusObjectPath &path)
265 m_recordPaths.append(path);
270 m_recordPathsCollectedTimer.start(100);
272 m_readErrorTimer.stop();
275void QNearFieldTargetPrivateImpl::createNdefMessage()
277 if (m_readRequested) {
278 qCDebug(QT_NFC_NEARD) <<
"creating Ndef message, reading" << m_recordPaths.length() <<
"record paths";
279 QNdefMessage newNdefMessage;
280 for (
const QDBusObjectPath &recordPath : std::as_const(m_recordPaths))
281 newNdefMessage.append(readRecord(recordPath));
283 if (!newNdefMessage.isEmpty()) {
284 QMetaObject::invokeMethod(
this,
"ndefMessageRead", Qt::QueuedConnection,
285 Q_ARG(QNdefMessage, newNdefMessage));
287 QMetaObject::invokeMethod(
this, [
this]() {
288 Q_EMIT requestCompleted(m_currentReadRequestId);
289 }, Qt::QueuedConnection);
291 reportError(QNearFieldTarget::UnknownError, m_currentReadRequestId);
294 m_readRequested =
false;
296 m_currentReadRequestId = QNearFieldTarget::RequestId(0);
300void QNearFieldTargetPrivateImpl::handleReadError()
302 reportError(QNearFieldTarget::UnknownError, m_currentReadRequestId);
303 m_currentReadRequestId = QNearFieldTarget::RequestId(0);
306void QNearFieldTargetPrivateImpl::handleWriteRequest()
308 OrgNeardTagInterface tagInterface(QStringLiteral(
"org.neard"), m_tagPath.path(),
309 QDBusConnection::systemBus());
310 if (!tagInterface.isValid()) {
311 qCWarning(QT_NFC_NEARD) <<
"tag interface invalid";
313 QDBusPendingReply<> reply;
314 reply = tagInterface.Write(m_currentWriteRequestData);
315 reply.waitForFinished();
316 if (reply.isError()) {
317 qCWarning(QT_NFC_NEARD) <<
"Error writing to NFC tag" << reply.error();
318 reportError(QNearFieldTarget::UnknownError, m_currentWriteRequestId);
321 QMetaObject::invokeMethod(
this, [
this]() {
322 Q_EMIT requestCompleted(m_currentWriteRequestId);
323 }, Qt::QueuedConnection);
327 m_currentWriteRequestId = QNearFieldTarget::RequestId(0);