Neard: fix tag writing

The write operation has to be delayed since neard isn't able
to write to tags immediately after tag detection.

Change-Id: I177cc700d0688e23909b9b2751a0d11f163a5499
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
This commit is contained in:
Martin Leutelt 2014-12-19 11:34:59 +01:00 committed by Alex Blasche
parent ad72ff0200
commit a804c20c3f
1 changed files with 59 additions and 38 deletions

View File

@ -76,6 +76,7 @@ public:
{ {
m_readErrorTimer.setSingleShot(true); m_readErrorTimer.setSingleShot(true);
m_recordPathsCollectedTimer.setSingleShot(true); m_recordPathsCollectedTimer.setSingleShot(true);
m_delayedWriteTimer.setSingleShot(true);
qCDebug(QT_NFC_NEARD) << "tag found at path" << interfacePath.path(); qCDebug(QT_NFC_NEARD) << "tag found at path" << interfacePath.path();
m_dbusProperties = new OrgFreedesktopDBusPropertiesInterface(QStringLiteral("org.neard"), m_dbusProperties = new OrgFreedesktopDBusPropertiesInterface(QStringLiteral("org.neard"),
@ -112,6 +113,8 @@ public:
this, &NearFieldTarget::createNdefMessage); this, &NearFieldTarget::createNdefMessage);
QObject::connect(&m_readErrorTimer, &QTimer::timeout, QObject::connect(&m_readErrorTimer, &QTimer::timeout,
this, &NearFieldTarget::handleReadError); this, &NearFieldTarget::handleReadError);
QObject::connect(&m_delayedWriteTimer, &QTimer::timeout,
this, &NearFieldTarget::handleWriteRequest);
QObject::connect(NeardHelper::instance(), &NeardHelper::recordFound, QObject::connect(NeardHelper::instance(), &NeardHelper::recordFound,
this, &NearFieldTarget::handleRecordFound); this, &NearFieldTarget::handleRecordFound);
} }
@ -151,12 +154,12 @@ public:
if (isValid()) { if (isValid()) {
// if the user calls readNdefMessages before the previous request has been completed // if the user calls readNdefMessages before the previous request has been completed
// return the current request id. // return the current request id.
if (m_currentRequestId.isValid()) if (m_currentReadRequestId.isValid())
return m_currentRequestId; return m_currentReadRequestId;
QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate()); QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate());
// save the id so it can be passed along with requestCompleted // save the id so it can be passed along with requestCompleted
m_currentRequestId = requestId; m_currentReadRequestId = requestId;
// since the triggering of interfaceAdded will ultimately lead to createNdefMessage being called // since the triggering of interfaceAdded will ultimately lead to createNdefMessage being called
// we need to make sure that ndefMessagesRead will only be triggered when readNdefMessages has // we need to make sure that ndefMessagesRead will only be triggered when readNdefMessages has
// been called before. In case readNdefMessages is called again after that we can directly call // been called before. In case readNdefMessages is called again after that we can directly call
@ -187,6 +190,10 @@ public:
QNearFieldTarget::RequestId writeNdefMessages(const QList<QNdefMessage> &messages) QNearFieldTarget::RequestId writeNdefMessages(const QList<QNdefMessage> &messages)
{ {
// return old request id when previous write request hasn't completed
if (m_currentWriteRequestId.isValid())
return m_currentReadRequestId;
qCDebug(QT_NFC_NEARD) << "writing messages"; qCDebug(QT_NFC_NEARD) << "writing messages";
if (messages.isEmpty() || messages.first().isEmpty()) { if (messages.isEmpty() || messages.first().isEmpty()) {
qCWarning(QT_NFC_NEARD) << "No record specified"; qCWarning(QT_NFC_NEARD) << "No record specified";
@ -200,50 +207,34 @@ public:
QNdefRecord record = messages.first().first(); QNdefRecord record = messages.first().first();
if (record.typeNameFormat() == QNdefRecord::NfcRtd) { if (record.typeNameFormat() == QNdefRecord::NfcRtd) {
QVariantMap recordProperties; m_currentWriteRequestData.clear();
if (record.isRecordType<QNdefNfcUriRecord>()) { if (record.isRecordType<QNdefNfcUriRecord>()) {
recordProperties.insert(QStringLiteral("Type"), QStringLiteral("URI")); m_currentWriteRequestData.insert(QStringLiteral("Type"), QStringLiteral("URI"));
QNdefNfcUriRecord uriRecord = static_cast<QNdefNfcUriRecord>(record); QNdefNfcUriRecord uriRecord = static_cast<QNdefNfcUriRecord>(record);
recordProperties.insert(QStringLiteral("URI"), uriRecord.uri().toString()); m_currentWriteRequestData.insert(QStringLiteral("URI"), uriRecord.uri().toString());
} else if (record.isRecordType<QNdefNfcSmartPosterRecord>()) { } else if (record.isRecordType<QNdefNfcSmartPosterRecord>()) {
recordProperties.insert(QStringLiteral("Type"), QStringLiteral("SmartPoster")); m_currentWriteRequestData.insert(QStringLiteral("Type"), QStringLiteral("SmartPoster"));
QNdefNfcSmartPosterRecord spRecord = static_cast<QNdefNfcSmartPosterRecord>(record); QNdefNfcSmartPosterRecord spRecord = static_cast<QNdefNfcSmartPosterRecord>(record);
recordProperties.insert(QStringLiteral("URI"), spRecord.uri().toString()); m_currentWriteRequestData.insert(QStringLiteral("URI"), spRecord.uri().toString());
// Currently neard only supports the uri property for writing // Currently neard only supports the uri property for writing
} else if (record.isRecordType<QNdefNfcTextRecord>()) { } else if (record.isRecordType<QNdefNfcTextRecord>()) {
recordProperties.insert(QStringLiteral("Type"), QStringLiteral("Text")); m_currentWriteRequestData.insert(QStringLiteral("Type"), QStringLiteral("Text"));
QNdefNfcTextRecord textRecord = static_cast<QNdefNfcTextRecord>(record); QNdefNfcTextRecord textRecord = static_cast<QNdefNfcTextRecord>(record);
recordProperties.insert(QStringLiteral("Representation"), textRecord.text()); m_currentWriteRequestData.insert(QStringLiteral("Representation"), textRecord.text());
recordProperties.insert(QStringLiteral("Encoding"), m_currentWriteRequestData.insert(QStringLiteral("Encoding"),
textRecord.encoding() == QNdefNfcTextRecord::Utf8 ? textRecord.encoding() == QNdefNfcTextRecord::Utf8 ?
QStringLiteral("UTF-8") : QStringLiteral("UTF-16") ); QStringLiteral("UTF-8") : QStringLiteral("UTF-16") );
recordProperties.insert(QStringLiteral("Language"), textRecord.locale()); m_currentWriteRequestData.insert(QStringLiteral("Language"), textRecord.locale());
} else { } else {
qCWarning(QT_NFC_NEARD) << "Record type not supported for writing"; qCWarning(QT_NFC_NEARD) << "Record type not supported for writing";
return QNearFieldTarget::RequestId(); return QNearFieldTarget::RequestId();
} }
OrgNeardTagInterface tagInterface(QStringLiteral("org.neard"), m_currentWriteRequestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate());
m_tagPath.path(), // trigger delayed write
QDBusConnection::systemBus()); m_delayedWriteTimer.start(100);
if (!tagInterface.isValid()) {
qCWarning(QT_NFC_NEARD) << "tag interface invalid";
} else {
QDBusPendingReply<> reply;
reply = tagInterface.Write(recordProperties);
reply.waitForFinished();
if (reply.isError()) {
qCWarning(QT_NFC_NEARD) << "Error writing to NFC tag" << reply.error();
return QNearFieldTarget::RequestId();
}
QMetaObject::invokeMethod(this, "ndefMessagesWritten", Qt::QueuedConnection); return m_currentWriteRequestId;
QNearFieldTarget::RequestId requestId = QNearFieldTarget::RequestId(new QNearFieldTarget::RequestIdPrivate());
QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection,
Q_ARG(const QNearFieldTarget::RequestId, requestId));
return requestId;
}
} }
return QNearFieldTarget::RequestId(); return QNearFieldTarget::RequestId();
@ -351,23 +342,50 @@ private:
Q_ARG(const QNdefMessage, newNdefMessage)); Q_ARG(const QNdefMessage, newNdefMessage));
// the request id in requestCompleted has to match the one created in readNdefMessages // the request id in requestCompleted has to match the one created in readNdefMessages
QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection,
Q_ARG(const QNearFieldTarget::RequestId, m_currentRequestId)); Q_ARG(const QNearFieldTarget::RequestId, m_currentReadRequestId));
} else { } else {
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(const QNearFieldTarget::Error, QNearFieldTarget::UnknownError), Q_ARG(const QNearFieldTarget::Error, QNearFieldTarget::UnknownError),
Q_ARG(const QNearFieldTarget::RequestId, m_currentRequestId)); Q_ARG(const QNearFieldTarget::RequestId, m_currentReadRequestId));
} }
m_readRequested = false; m_readRequested = false;
// invalidate the current request id // invalidate the current request id
m_currentRequestId = QNearFieldTarget::RequestId(0); m_currentReadRequestId = QNearFieldTarget::RequestId(0);
} }
} }
void handleReadError() void handleReadError()
{ {
emit QNearFieldTarget::error(QNearFieldTarget::UnknownError, m_currentRequestId); emit QNearFieldTarget::error(QNearFieldTarget::UnknownError, m_currentReadRequestId);
m_currentRequestId = QNearFieldTarget::RequestId(0); m_currentReadRequestId = QNearFieldTarget::RequestId(0);
}
void handleWriteRequest()
{
OrgNeardTagInterface tagInterface(QStringLiteral("org.neard"),
m_tagPath.path(),
QDBusConnection::systemBus());
if (!tagInterface.isValid()) {
qCWarning(QT_NFC_NEARD) << "tag interface invalid";
} else {
QDBusPendingReply<> reply;
reply = tagInterface.Write(m_currentWriteRequestData);
reply.waitForFinished();
if (reply.isError()) {
qCWarning(QT_NFC_NEARD) << "Error writing to NFC tag" << reply.error();
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
Q_ARG(const QNearFieldTarget::Error, QNearFieldTarget::UnknownError),
Q_ARG(const QNearFieldTarget::RequestId, m_currentWriteRequestId));
}
QMetaObject::invokeMethod(this, "ndefMessagesWritten", Qt::QueuedConnection);
QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection,
Q_ARG(const QNearFieldTarget::RequestId, m_currentWriteRequestId));
}
// invalidate current write request
m_currentWriteRequestId = QNearFieldTarget::RequestId(0);
} }
protected: protected:
@ -376,9 +394,12 @@ protected:
QList<QDBusObjectPath> m_recordPaths; QList<QDBusObjectPath> m_recordPaths;
QTimer m_recordPathsCollectedTimer; QTimer m_recordPathsCollectedTimer;
QTimer m_readErrorTimer; QTimer m_readErrorTimer;
QTimer m_delayedWriteTimer;
QNearFieldTarget::Type m_type; QNearFieldTarget::Type m_type;
bool m_readRequested; bool m_readRequested;
QNearFieldTarget::RequestId m_currentRequestId; QNearFieldTarget::RequestId m_currentReadRequestId;
QNearFieldTarget::RequestId m_currentWriteRequestId;
QVariantMap m_currentWriteRequestData;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE