From a60c1cb3c4afd6dfd305115ec4c52e993172fa7d Mon Sep 17 00:00:00 2001 From: Javier Date: Sun, 7 Dec 2014 23:39:29 +0100 Subject: ability to upload apps --- daemon/uploadmanager.cpp | 266 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 daemon/uploadmanager.cpp (limited to 'daemon/uploadmanager.cpp') diff --git a/daemon/uploadmanager.cpp b/daemon/uploadmanager.cpp new file mode 100644 index 0000000..89d70f7 --- /dev/null +++ b/daemon/uploadmanager.cpp @@ -0,0 +1,266 @@ +#include "uploadmanager.h" +#include "unpacker.h" +#include "packer.h" +#include "stm32crc.h" + +static const int CHUNK_SIZE = 2000; +using std::function; + +UploadManager::UploadManager(WatchConnector *watch, QObject *parent) : + QObject(parent), watch(watch), _lastUploadId(0), _state(StateNotStarted) +{ + watch->setEndpointHandler(WatchConnector::watchPUTBYTES, + [this](const QByteArray &msg) { + if (_pending.empty()) { + logger()->warn() << "putbytes message, but queue is empty!"; + return false; + } + handleMessage(msg); + return true; + }); +} + +uint UploadManager::upload(WatchConnector::UploadType type, int index, QIODevice *device, int size, + function successCallback, function errorCallback) +{ + PendingUpload upload; + upload.id = ++_lastUploadId; + upload.type = type; + upload.index = index; + upload.device = device; + if (size < 0) { + upload.remaining = device->size(); + } else { + upload.remaining = size; + } + upload.successCallback = successCallback; + upload.errorCallback = errorCallback; + + if (upload.remaining <= 0) { + logger()->warn() << "upload is empty"; + if (errorCallback) { + errorCallback(-1); + return -1; + } + } + + _pending.enqueue(upload); + + if (_pending.size() == 1) { + startNextUpload(); + } + + return upload.id; +} + +void UploadManager::cancel(uint id, int code) +{ + if (_pending.empty()) { + logger()->warn() << "cannot cancel, empty queue"; + return; + } + + if (id == _pending.head().id) { + PendingUpload upload = _pending.dequeue(); + logger()->debug() << "aborting current upload" << id << "(code:" << code << ")"; + + if (_state != StateNotStarted && _state != StateWaitForToken && _state != StateComplete) { + QByteArray msg; + Packer p(&msg); + p.write(WatchConnector::putbytesABORT); + p.write(_token); + + logger()->debug() << "sending abort for upload" << id; + + watch->sendMessage(WatchConnector::watchPUTBYTES, msg); + } + + _state = StateNotStarted; + _token = 0; + + if (upload.errorCallback) { + upload.errorCallback(code); + } + + if (!_pending.empty()) { + startNextUpload(); + } + } else { + for (int i = 1; i < _pending.size(); ++i) { + if (_pending[i].id == id) { + logger()->debug() << "cancelling upload" << id << "(code:" << code << ")"; + if (_pending[i].errorCallback) { + _pending[i].errorCallback(code); + } + _pending.removeAt(i); + return; + } + } + logger()->warn() << "cannot cancel, id" << id << "not found"; + } +} + +void UploadManager::startNextUpload() +{ + Q_ASSERT(!_pending.empty()); + Q_ASSERT(_state == StateNotStarted); + + PendingUpload &upload = _pending.head(); + QByteArray msg; + Packer p(&msg); + p.write(WatchConnector::putbytesINIT); + p.write(upload.remaining); + p.write(upload.type); + p.write(upload.index); + + _state = StateWaitForToken; + watch->sendMessage(WatchConnector::watchPUTBYTES, msg); +} + +void UploadManager::handleMessage(const QByteArray &msg) +{ + Q_ASSERT(!_pending.empty()); + PendingUpload &upload = _pending.head(); + + logger()->debug() << "get message" << msg.toHex(); + + Unpacker u(msg); + int status = u.read(); + + if (u.bad() || status != 1) { + logger()->warn() << "upload" << upload.id << "got error code=" << status; + cancel(upload.id, status); + return; + } + + quint32 recv_token = u.read(); + + if (u.bad()) { + logger()->warn() << "upload" << upload.id << ": could not read the token"; + cancel(upload.id, -1); + return; + } + + if (_state != StateNotStarted && _state != StateWaitForToken && _state != StateComplete) { + if (recv_token != _token) { + logger()->warn() << "upload" << upload.id << ": invalid token"; + cancel(upload.id, -1); + return; + } + } + + switch (_state) { + case StateNotStarted: + logger()->warn() << "got packet when upload is not started"; + break; + case StateWaitForToken: + logger()->debug() << "token received"; + _token = recv_token; + _state = StateInProgress; + + /* fallthrough */ + case StateInProgress: + logger()->debug() << "moving to the next chunk"; + if (upload.remaining > 0) { + if (!uploadNextChunk(upload)) { + cancel(upload.id, -1); + return; + } + } else { + logger()->debug() << "no additional chunks, commit"; + _state = StateCommit; + if (!commit(upload)) { + cancel(upload.id, -1); + return; + } + } + break; + case StateCommit: + logger()->debug() << "commited succesfully"; + _state = StateComplete; + if (!complete(upload)) { + cancel(upload.id, -1); + return; + } + break; + case StateComplete: + logger()->debug() << "upload" << upload.id << "succesful, invoking callback"; + if (upload.successCallback) { + upload.successCallback(); + } + _pending.dequeue(); + _token = 0; + _state = StateNotStarted; + if (!_pending.empty()) { + startNextUpload(); + } + break; + } +} + +bool UploadManager::uploadNextChunk(PendingUpload &upload) +{ + QByteArray chunk = upload.device->read(qMin(upload.remaining, CHUNK_SIZE)); + + if (upload.remaining < CHUNK_SIZE && chunk.size() < upload.remaining) { + // Short read! + logger()->warn() << "short read during upload" << upload.id; + return false; + } + + Q_ASSERT(!chunk.isEmpty()); + Q_ASSERT(_state = StateInProgress); + + QByteArray msg; + Packer p(&msg); + p.write(WatchConnector::putbytesSEND); + p.write(_token); + p.write(chunk.size()); + msg.append(chunk); + + logger()->debug() << "sending a chunk of" << chunk.size() << "bytes"; + + watch->sendMessage(WatchConnector::watchPUTBYTES, msg); + + upload.remaining -= chunk.size(); + upload.crc.addData(chunk); + + logger()->debug() << "remaining" << upload.remaining << "bytes"; + + return true; +} + +bool UploadManager::commit(PendingUpload &upload) +{ + Q_ASSERT(_state == StateCommit); + Q_ASSERT(upload.remaining == 0); + + QByteArray msg; + Packer p(&msg); + p.write(WatchConnector::putbytesCOMMIT); + p.write(_token); + p.write(upload.crc.result()); + + logger()->debug() << "commiting upload" << upload.id + << "with crc" << qPrintable(QString("0x%1").arg(upload.crc.result(), 0, 16)); + + watch->sendMessage(WatchConnector::watchPUTBYTES, msg); + + return true; +} + +bool UploadManager::complete(PendingUpload &upload) +{ + Q_ASSERT(_state == StateComplete); + + QByteArray msg; + Packer p(&msg); + p.write(WatchConnector::putbytesCOMPLETE); + p.write(_token); + + logger()->debug() << "completing upload" << upload.id; + + watch->sendMessage(WatchConnector::watchPUTBYTES, msg); + + return true; +} -- cgit v1.2.3 From 4280a9bda38046f702a4151d7b831a3bf46ef169 Mon Sep 17 00:00:00 2001 From: Javier Date: Mon, 8 Dec 2014 00:16:06 +0100 Subject: add d-bus API to list slot contents and fix other API issues --- daemon/bankmanager.cpp | 14 ++++++++++++++ daemon/bankmanager.h | 4 +++- daemon/manager.cpp | 25 +++++++++++++++++++++++-- daemon/manager.h | 8 ++++++-- daemon/uploadmanager.cpp | 5 +++-- daemon/watchconnector.cpp | 16 +++++++++------- daemon/watchconnector.h | 1 - org.pebbled.Watch.xml | 6 ++++-- 8 files changed, 62 insertions(+), 17 deletions(-) (limited to 'daemon/uploadmanager.cpp') diff --git a/daemon/bankmanager.cpp b/daemon/bankmanager.cpp index fe5dc21..8636e95 100644 --- a/daemon/bankmanager.cpp +++ b/daemon/bankmanager.cpp @@ -21,6 +21,16 @@ int BankManager::numSlots() const return _slots.size(); } +bool BankManager::isUsed(int slot) const +{ + return _slots.at(slot).used; +} + +QUuid BankManager::appAt(int slot) const +{ + return _slots.at(slot).uuid; +} + bool BankManager::uploadApp(const QUuid &uuid, int slot) { AppInfo info = apps->info(uuid); @@ -39,6 +49,10 @@ bool BankManager::uploadApp(const QUuid &uuid, int slot) logger()->warn() << "invalid slot index"; return false; } + if (_slots[slot].used) { + logger()->warn() << "slot in use"; + return false; + } QDir appDir(info.path()); diff --git a/daemon/bankmanager.h b/daemon/bankmanager.h index 6abedc8..871db6b 100644 --- a/daemon/bankmanager.h +++ b/daemon/bankmanager.h @@ -15,6 +15,9 @@ public: int numSlots() const; + bool isUsed(int slot) const; + QUuid appAt(int slot) const; + signals: void slotsChanged(); @@ -28,7 +31,6 @@ private: int findUnusedSlot() const; void refreshWatchApp(int slot, std::function successCallback, std::function errorCallback); - private slots: void handleWatchConnected(); diff --git a/daemon/manager.cpp b/daemon/manager.cpp index 136d7f3..469e92b 100644 --- a/daemon/manager.cpp +++ b/daemon/manager.cpp @@ -70,6 +70,7 @@ Manager::Manager(Settings *settings, QObject *parent) : connect(dbus, &DBusConnector::pebbleChanged, proxy, &PebbledProxy::NameChanged); connect(dbus, &DBusConnector::pebbleChanged, proxy, &PebbledProxy::AddressChanged); connect(watch, &WatchConnector::connectedChanged, proxy, &PebbledProxy::ConnectedChanged); + connect(bank, &BankManager::slotsChanged, proxy, &PebbledProxy::AppSlotsChanged); QString currentProfile = getCurrentProfile(); defaultProfile = currentProfile.isEmpty() ? "ambience" : currentProfile; @@ -414,6 +415,26 @@ void Manager::onAppClosed(const QUuid &uuid) emit proxy->AppUuidChanged(); } +QStringList PebbledProxy::AppSlots() const +{ + const int num_slots = manager()->bank->numSlots(); + QStringList l; + l.reserve(num_slots); + + for (int i = 0; i < num_slots; ++i) { + if (manager()->bank->isUsed(i)) { + QUuid uuid = manager()->bank->appAt(i); + l.append(uuid.toString()); + } else { + l.append(QString()); + } + } + + Q_ASSERT(l.size() == num_slots); + + return l; +} + bool PebbledProxy::SendAppMessage(const QString &uuid, const QVariantMap &data) { Q_ASSERT(calledFromDBus()); @@ -501,7 +522,7 @@ void PebbledProxy::SendAppConfigurationData(const QString &uuid, const QString & manager()->js->handleWebviewClosed(data); } -void PebbledProxy::UnloadApp(uint slot) +void PebbledProxy::UnloadApp(int slot) { Q_ASSERT(calledFromDBus()); const QDBusMessage msg = message(); @@ -512,7 +533,7 @@ void PebbledProxy::UnloadApp(uint slot) } } -void PebbledProxy::UploadApp(const QString &uuid, uint slot) +void PebbledProxy::UploadApp(const QString &uuid, int slot) { Q_ASSERT(calledFromDBus()); const QDBusMessage msg = message(); diff --git a/daemon/manager.h b/daemon/manager.h index f27da98..0588705 100644 --- a/daemon/manager.h +++ b/daemon/manager.h @@ -122,6 +122,7 @@ class PebbledProxy : public QObject, protected QDBusContext Q_PROPERTY(QString Address READ Address NOTIFY AddressChanged) Q_PROPERTY(bool Connected READ Connected NOTIFY ConnectedChanged) Q_PROPERTY(QString AppUuid READ AppUuid NOTIFY AppUuidChanged) + Q_PROPERTY(QStringList AppSlots READ AppSlots NOTIFY AppSlotsChanged) inline Manager* manager() const { return static_cast(parent()); } inline QVariantMap pebble() const { return manager()->dbus->pebble(); } @@ -134,6 +135,8 @@ public: inline bool Connected() const { return manager()->watch->isConnected(); } inline QString AppUuid() const { return manager()->currentAppUuid.toString(); } + QStringList AppSlots() const; + public slots: inline void Disconnect() { manager()->watch->disconnect(); } inline void Reconnect() { manager()->watch->reconnect(); } @@ -147,14 +150,15 @@ public slots: QString StartAppConfiguration(const QString &uuid); void SendAppConfigurationData(const QString &uuid, const QString &data); - void UnloadApp(uint slot); - void UploadApp(const QString &uuid, uint slot); + void UnloadApp(int slot); + void UploadApp(const QString &uuid, int slot); signals: void NameChanged(); void AddressChanged(); void ConnectedChanged(); void AppUuidChanged(); + void AppSlotsChanged(); void AppOpened(const QString &uuid); void AppClosed(const QString &uuid); }; diff --git a/daemon/uploadmanager.cpp b/daemon/uploadmanager.cpp index 89d70f7..ccbf12a 100644 --- a/daemon/uploadmanager.cpp +++ b/daemon/uploadmanager.cpp @@ -122,8 +122,6 @@ void UploadManager::handleMessage(const QByteArray &msg) Q_ASSERT(!_pending.empty()); PendingUpload &upload = _pending.head(); - logger()->debug() << "get message" << msg.toHex(); - Unpacker u(msg); int status = u.read(); @@ -195,6 +193,9 @@ void UploadManager::handleMessage(const QByteArray &msg) startNextUpload(); } break; + default: + logger()->warn() << "received message in wrong state"; + break; } } diff --git a/daemon/watchconnector.cpp b/daemon/watchconnector.cpp index 21f5ad5..e66ec0f 100644 --- a/daemon/watchconnector.cpp +++ b/daemon/watchconnector.cpp @@ -5,6 +5,7 @@ #include "unpacker.h" static const int RECONNECT_TIMEOUT = 500; //ms +static const bool PROTOCOL_DEBUG = false; using std::function; @@ -135,7 +136,7 @@ bool WatchConnector::dispatchMessage(uint endpoint, const QByteArray &data) } logger()->info() << "message to endpoint" << decodeEndpoint(endpoint) << "was not dispatched"; - emit messageReceived(endpoint, data); + logger()->debug() << data.toHex(); return false; } @@ -182,6 +183,7 @@ void WatchConnector::onReadSocket() QByteArray data = socket->read(message_length); logger()->debug() << "received message of length" << message_length << "to endpoint" << decodeEndpoint(endpoint); + if (PROTOCOL_DEBUG) logger()->debug() << data.toHex(); dispatchMessage(endpoint, data); } @@ -225,7 +227,7 @@ void WatchConnector::onDisconnected() reconnectTimer.setInterval(reconnectTimer.interval() + RECONNECT_TIMEOUT); } reconnectTimer.start(); - logger()->debug() << "Will reconnect in" << reconnectTimer.interval() << "ms"; + logger()->debug() << "will reconnect in" << reconnectTimer.interval() << "ms"; } void WatchConnector::onError(QBluetoothSocket::SocketError error) @@ -233,7 +235,7 @@ void WatchConnector::onError(QBluetoothSocket::SocketError error) if (error == QBluetoothSocket::UnknownSocketError) { logger()->info() << error << socket->errorString(); } else { - logger()->error() << "Error connecting Pebble:" << error << socket->errorString(); + logger()->error() << "error connecting Pebble:" << error << socket->errorString(); } } @@ -241,11 +243,11 @@ void WatchConnector::sendData(const QByteArray &data) { writeData.append(data); if (socket == nullptr) { - logger()->debug() << "No socket - reconnecting"; + logger()->debug() << "no socket - reconnecting"; reconnect(); } else if (is_connected) { - logger()->debug() << "Writing" << data.length() << "bytes to socket"; - logger()->debug() << data.toHex(); + logger()->debug() << "writing" << data.length() << "bytes to socket"; + if (PROTOCOL_DEBUG) logger()->debug() << data.toHex(); socket->write(data); } } @@ -253,7 +255,7 @@ void WatchConnector::sendData(const QByteArray &data) void WatchConnector::onBytesWritten(qint64 bytes) { writeData.remove(0, bytes); - logger()->debug() << "Socket written" << bytes << "bytes," << writeData.length() << "left"; + logger()->debug() << "socket written" << bytes << "bytes," << writeData.length() << "left"; } void WatchConnector::sendMessage(uint endpoint, const QByteArray &data, const EndpointHandlerFunc &callback) diff --git a/daemon/watchconnector.h b/daemon/watchconnector.h index 1aaf39d..2e89b8c 100644 --- a/daemon/watchconnector.h +++ b/daemon/watchconnector.h @@ -193,7 +193,6 @@ public: static QString decodeEndpoint(uint val); signals: - void messageReceived(uint endpoint, const QByteArray &data); void nameChanged(); void connectedChanged(); diff --git a/org.pebbled.Watch.xml b/org.pebbled.Watch.xml index 2c5202f..e076d6c 100644 --- a/org.pebbled.Watch.xml +++ b/org.pebbled.Watch.xml @@ -51,12 +51,14 @@ + + - + - + -- cgit v1.2.3 From 8c86d80504bec6524d9c5006d168438500130ca5 Mon Sep 17 00:00:00 2001 From: Javier Date: Fri, 12 Dec 2014 01:03:56 +0100 Subject: add support for uploading files, requires fw 2.8 --- daemon/bankmanager.cpp | 24 ++++++++++++++++++++++-- daemon/packer.cpp | 6 ++++++ daemon/packer.h | 2 ++ daemon/uploadmanager.cpp | 26 ++++++++++++++++++++++++-- daemon/uploadmanager.h | 14 ++++++++++---- log4qt-debug.conf | 2 +- 6 files changed, 65 insertions(+), 9 deletions(-) (limited to 'daemon/uploadmanager.cpp') diff --git a/daemon/bankmanager.cpp b/daemon/bankmanager.cpp index 331dd6a..dd278af 100644 --- a/daemon/bankmanager.cpp +++ b/daemon/bankmanager.cpp @@ -4,6 +4,26 @@ #include "packer.h" #include "bankmanager.h" +#if 0 +// TODO -- This is how language files seems to be installed. +if (slot == -4) { + logger()->debug() << "starting lang install"; + QFile *pbl = new QFile(QDir::home().absoluteFilePath("es.pbl")); + if (!pbl->open(QIODevice::ReadOnly)) { + logger()->warn() << "Failed to open pbl"; + return false; + } + + upload->uploadFile("lang", pbl, [this]() { + logger()->debug() << "success"; + }, [this](int code) { + logger()->warn() << "Some error" << code; + }); + + return true; +} +#endif + BankManager::BankManager(WatchConnector *watch, UploadManager *upload, AppManager *apps, QObject *parent) : QObject(parent), watch(watch), upload(upload), apps(apps), _refresh(new QTimer(this)) { @@ -82,14 +102,14 @@ bool BankManager::uploadApp(const QUuid &uuid, int slot) _slots[slot].name.clear(); _slots[slot].uuid = QUuid(); - upload->upload(WatchConnector::uploadBINARY, slot, binaryFile, -1, + upload->uploadAppBinary(slot, binaryFile, [this, binaryFile, resourceFile, slot]() { logger()->debug() << "app binary upload succesful"; delete binaryFile; // Proceed to upload the resource file if (resourceFile) { - upload->upload(WatchConnector::uploadRESOURCES, slot, resourceFile, -1, + upload->uploadAppResources(slot, resourceFile, [this, resourceFile, slot]() { logger()->debug() << "app resources upload succesful"; delete resourceFile; diff --git a/daemon/packer.cpp b/daemon/packer.cpp index 0cc71f6..00d5383 100644 --- a/daemon/packer.cpp +++ b/daemon/packer.cpp @@ -14,6 +14,12 @@ void Packer::writeBytes(int n, const QByteArray &b) } } +void Packer::writeCString(const QString &s) +{ + _buf->append(s.toUtf8()); + _buf->append('\0'); +} + void Packer::writeUuid(const QUuid &uuid) { writeBytes(16, uuid.toRfc4122()); diff --git a/daemon/packer.h b/daemon/packer.h index d22072c..ceb6593 100644 --- a/daemon/packer.h +++ b/daemon/packer.h @@ -25,6 +25,8 @@ public: void writeFixedString(int n, const QString &s); + void writeCString(const QString &s); + void writeUuid(const QUuid &uuid); void writeDict(const QMap &d); diff --git a/daemon/uploadmanager.cpp b/daemon/uploadmanager.cpp index ccbf12a..29c436e 100644 --- a/daemon/uploadmanager.cpp +++ b/daemon/uploadmanager.cpp @@ -20,13 +20,14 @@ UploadManager::UploadManager(WatchConnector *watch, QObject *parent) : }); } -uint UploadManager::upload(WatchConnector::UploadType type, int index, QIODevice *device, int size, - function successCallback, function errorCallback) +uint UploadManager::upload(WatchConnector::UploadType type, int index, const QString &filename, QIODevice *device, int size, + SuccessCallback successCallback, ErrorCallback errorCallback) { PendingUpload upload; upload.id = ++_lastUploadId; upload.type = type; upload.index = index; + upload.filename = filename; upload.device = device; if (size < 0) { upload.remaining = device->size(); @@ -53,6 +54,22 @@ uint UploadManager::upload(WatchConnector::UploadType type, int index, QIODevice return upload.id; } +uint UploadManager::uploadAppBinary(int slot, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback) +{ + return upload(WatchConnector::uploadBINARY, slot, QString(), device, -1, successCallback, errorCallback); +} + +uint UploadManager::uploadAppResources(int slot, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback) +{ + return upload(WatchConnector::uploadRESOURCES, slot, QString(), device, -1, successCallback, errorCallback); +} + +uint UploadManager::uploadFile(const QString &filename, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback) +{ + Q_ASSERT(!filename.isEmpty()); + return upload(WatchConnector::uploadFILE, 0, filename, device, -1, successCallback, errorCallback); +} + void UploadManager::cancel(uint id, int code) { if (_pending.empty()) { @@ -112,6 +129,11 @@ void UploadManager::startNextUpload() p.write(upload.remaining); p.write(upload.type); p.write(upload.index); + if (!upload.filename.isEmpty()) { + p.writeCString(upload.filename); + } + + logger()->debug() << "starting new upload, size:" << upload.remaining << ", type:" << upload.type << ", slot:" << upload.index; _state = StateWaitForToken; watch->sendMessage(WatchConnector::watchPUTBYTES, msg); diff --git a/daemon/uploadmanager.h b/daemon/uploadmanager.h index 1d42237..b4e951a 100644 --- a/daemon/uploadmanager.h +++ b/daemon/uploadmanager.h @@ -14,11 +14,16 @@ class UploadManager : public QObject public: explicit UploadManager(WatchConnector *watch, QObject *parent = 0); - typedef std::function Callback; + typedef std::function SuccessCallback; + typedef std::function ErrorCallback; + + uint upload(WatchConnector::UploadType type, int index, const QString &filename, QIODevice *device, int size = -1, + SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); + + uint uploadAppBinary(int slot, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); + uint uploadAppResources(int slot, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); + uint uploadFile(const QString &filename, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); - uint upload(WatchConnector::UploadType type, int index, QIODevice *device, int size = -1, - std::function successCallback = std::function(), - std::function errorCallback = std::function()); void cancel(uint id, int code = 0); signals: @@ -40,6 +45,7 @@ private: WatchConnector::UploadType type; int index; + QString filename; QIODevice *device; int remaining; Stm32Crc crc; diff --git a/log4qt-debug.conf b/log4qt-debug.conf index 2d55cdc..1baed5d 100644 --- a/log4qt-debug.conf +++ b/log4qt-debug.conf @@ -1,4 +1,4 @@ -log4j.rootLogger=DEBUG, consolelog, syslog +log4j.rootLogger=TRACE, consolelog, syslog log4j.appender.consolelog=org.apache.log4j.ColorConsoleAppender log4j.appender.consolelog.layout=org.apache.log4j.SimpleTimeLayout -- cgit v1.2.3 From e0fdb8c0f36fc78d3f445c3a218902bc132a33ec Mon Sep 17 00:00:00 2001 From: Javier Date: Sat, 13 Dec 2014 00:24:07 +0100 Subject: progress reporting callbacks in uploadmanager --- daemon/uploadmanager.cpp | 30 ++++++++++++++++++++---------- daemon/uploadmanager.h | 15 +++++++++------ 2 files changed, 29 insertions(+), 16 deletions(-) (limited to 'daemon/uploadmanager.cpp') diff --git a/daemon/uploadmanager.cpp b/daemon/uploadmanager.cpp index 29c436e..5976fe6 100644 --- a/daemon/uploadmanager.cpp +++ b/daemon/uploadmanager.cpp @@ -21,7 +21,7 @@ UploadManager::UploadManager(WatchConnector *watch, QObject *parent) : } uint UploadManager::upload(WatchConnector::UploadType type, int index, const QString &filename, QIODevice *device, int size, - SuccessCallback successCallback, ErrorCallback errorCallback) + SuccessCallback successCallback, ErrorCallback errorCallback, ProgressCallback progressCallback) { PendingUpload upload; upload.id = ++_lastUploadId; @@ -30,12 +30,14 @@ uint UploadManager::upload(WatchConnector::UploadType type, int index, const QSt upload.filename = filename; upload.device = device; if (size < 0) { - upload.remaining = device->size(); + upload.size = device->size(); } else { - upload.remaining = size; + upload.size = size; } + upload.remaining = upload.size; upload.successCallback = successCallback; upload.errorCallback = errorCallback; + upload.progressCallback = progressCallback; if (upload.remaining <= 0) { logger()->warn() << "upload is empty"; @@ -54,20 +56,20 @@ uint UploadManager::upload(WatchConnector::UploadType type, int index, const QSt return upload.id; } -uint UploadManager::uploadAppBinary(int slot, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback) +uint UploadManager::uploadAppBinary(int slot, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback, ProgressCallback progressCallback) { - return upload(WatchConnector::uploadBINARY, slot, QString(), device, -1, successCallback, errorCallback); + return upload(WatchConnector::uploadBINARY, slot, QString(), device, -1, successCallback, errorCallback, progressCallback); } -uint UploadManager::uploadAppResources(int slot, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback) +uint UploadManager::uploadAppResources(int slot, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback, ProgressCallback progressCallback) { - return upload(WatchConnector::uploadRESOURCES, slot, QString(), device, -1, successCallback, errorCallback); + return upload(WatchConnector::uploadRESOURCES, slot, QString(), device, -1, successCallback, errorCallback, progressCallback); } -uint UploadManager::uploadFile(const QString &filename, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback) +uint UploadManager::uploadFile(const QString &filename, QIODevice *device, SuccessCallback successCallback, ErrorCallback errorCallback, ProgressCallback progressCallback) { Q_ASSERT(!filename.isEmpty()); - return upload(WatchConnector::uploadFILE, 0, filename, device, -1, successCallback, errorCallback); + return upload(WatchConnector::uploadFILE, 0, filename, device, -1, successCallback, errorCallback, progressCallback); } void UploadManager::cancel(uint id, int code) @@ -181,6 +183,10 @@ void UploadManager::handleMessage(const QByteArray &msg) /* fallthrough */ case StateInProgress: logger()->debug() << "moving to the next chunk"; + if (upload.progressCallback) { + // Report that the previous chunk has been succesfully uploaded + upload.progressCallback(1.0 - (qreal(upload.remaining) / upload.size)); + } if (upload.remaining > 0) { if (!uploadNextChunk(upload)) { cancel(upload.id, -1); @@ -197,6 +203,10 @@ void UploadManager::handleMessage(const QByteArray &msg) break; case StateCommit: logger()->debug() << "commited succesfully"; + if (upload.progressCallback) { + // Report that all chunks have been succesfully uploaded + upload.progressCallback(1.0); + } _state = StateComplete; if (!complete(upload)) { cancel(upload.id, -1); @@ -248,7 +258,7 @@ bool UploadManager::uploadNextChunk(PendingUpload &upload) upload.remaining -= chunk.size(); upload.crc.addData(chunk); - logger()->debug() << "remaining" << upload.remaining << "bytes"; + logger()->debug() << "remaining" << upload.remaining << "/" << upload.size << "bytes"; return true; } diff --git a/daemon/uploadmanager.h b/daemon/uploadmanager.h index b4e951a..45453b6 100644 --- a/daemon/uploadmanager.h +++ b/daemon/uploadmanager.h @@ -16,13 +16,14 @@ public: typedef std::function SuccessCallback; typedef std::function ErrorCallback; + typedef std::function ProgressCallback; uint upload(WatchConnector::UploadType type, int index, const QString &filename, QIODevice *device, int size = -1, - SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); + SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback(), ProgressCallback progressCallback = ProgressCallback()); - uint uploadAppBinary(int slot, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); - uint uploadAppResources(int slot, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); - uint uploadFile(const QString &filename, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback()); + uint uploadAppBinary(int slot, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback(), ProgressCallback progressCallback = ProgressCallback()); + uint uploadAppResources(int slot, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback(), ProgressCallback progressCallback = ProgressCallback()); + uint uploadFile(const QString &filename, QIODevice *device, SuccessCallback successCallback = SuccessCallback(), ErrorCallback errorCallback = ErrorCallback(), ProgressCallback progressCallback = ProgressCallback()); void cancel(uint id, int code = 0); @@ -47,11 +48,13 @@ private: int index; QString filename; QIODevice *device; + int size; int remaining; Stm32Crc crc; - std::function successCallback; - std::function errorCallback; + SuccessCallback successCallback; + ErrorCallback errorCallback; + ProgressCallback progressCallback; }; void startNextUpload(); -- cgit v1.2.3