From cbb0039fe542c0d8281601d25c04de487c84fa17 Mon Sep 17 00:00:00 2001 From: Tomasz Sterna Date: Tue, 7 Apr 2015 15:40:14 +0200 Subject: Implemented checking for latest firmware version --- app/app.pro | 6 ++- app/pebble.cpp | 3 ++ app/pebbledinterface.cpp | 12 ++++++ app/pebbledinterface.h | 3 ++ app/pebblefirmware.cpp | 59 +++++++++++++++++++++++++++++ app/pebblefirmware.h | 38 +++++++++++++++++++ app/qml/pages/ManagerPage.qml | 31 --------------- app/qml/pages/WatchInfo.qml | 52 +++++++++++++++++-------- app/qml/pebble.qml | 88 ++++++++++++++++++++++++++++--------------- app/translations/pebble-es.ts | 86 +++++++++++++++++++++++++----------------- app/translations/pebble-pl.ts | 86 +++++++++++++++++++++++++----------------- app/translations/pebble.ts | 86 +++++++++++++++++++++++++----------------- daemon/daemon.pro | 5 +-- org.pebbled.Watch.xml | 6 +++ pebble.pro | 1 + 15 files changed, 374 insertions(+), 188 deletions(-) create mode 100644 app/pebblefirmware.cpp create mode 100644 app/pebblefirmware.h diff --git a/app/app.pro b/app/app.pro index 3810f90..18be5a5 100644 --- a/app/app.pro +++ b/app/app.pro @@ -11,12 +11,14 @@ SOURCES += \ pebble.cpp \ pebbledinterface.cpp \ pebbleappiconprovider.cpp \ - pebblestoreview.cpp + pebblestoreview.cpp \ + pebblefirmware.cpp HEADERS += \ pebbledinterface.h \ pebbleappiconprovider.h \ - pebblestoreview.h + pebblestoreview.h \ + pebblefirmware.h DBUS_INTERFACES += ../org.pebbled.Watch.xml diff --git a/app/pebble.cpp b/app/pebble.cpp index dd3c915..04ff6a8 100644 --- a/app/pebble.cpp +++ b/app/pebble.cpp @@ -34,6 +34,7 @@ #include #include "pebbledinterface.h" #include "pebbleappiconprovider.h" +#include "pebblefirmware.h" #include "pebblestoreview.h" int main(int argc, char *argv[]) @@ -54,9 +55,11 @@ int main(int argc, char *argv[]) QScopedPointer view(SailfishApp::createView()); QScopedPointer pebbled(new PebbledInterface); QScopedPointer appicons(new PebbleAppIconProvider(pebbled.data())); + QScopedPointer firmware(new PebbleFirmware); view->rootContext()->setContextProperty("APP_VERSION", APP_VERSION); view->rootContext()->setContextProperty("pebbled", pebbled.data()); + view->rootContext()->setContextProperty("pebbleFirmware", firmware.data()); view->engine()->addImageProvider("pebble-app-icon", appicons.data()); view->setSource(SailfishApp::pathTo("qml/pebble.qml")); view->show(); diff --git a/app/pebbledinterface.cpp b/app/pebbledinterface.cpp index e7fcb2e..28f0581 100644 --- a/app/pebbledinterface.cpp +++ b/app/pebbledinterface.cpp @@ -304,6 +304,18 @@ QVariantMap PebbledInterface::appInfoByUuid(const QString &uuid) const } } +void PebbledInterface::uploadFirmware(const QString &file) +{ + qDebug() << Q_FUNC_INFO << file; + QDBusPendingReply<> reply = watch->UploadFirmware(false, file); + reply.waitForFinished(); +} + +void PebbledInterface::notifyFirmware(const QString &version) +{ + qDebug() << Q_FUNC_INFO << version; +} + void PebbledInterface::onWatchConnectedChanged() { qDebug() << Q_FUNC_INFO; diff --git a/app/pebbledinterface.h b/app/pebbledinterface.h index cba5416..740df75 100644 --- a/app/pebbledinterface.h +++ b/app/pebbledinterface.h @@ -73,6 +73,9 @@ public slots: void uploadApp(const QString &uuid, int slot); void unloadApp(int slot); + void uploadFirmware(const QString &file); + void notifyFirmware(const QString &version); + private slots: void onWatchConnectedChanged(); void getUnitProperties(); diff --git a/app/pebblefirmware.cpp b/app/pebblefirmware.cpp new file mode 100644 index 0000000..95294f7 --- /dev/null +++ b/app/pebblefirmware.cpp @@ -0,0 +1,59 @@ +#include "pebblefirmware.h" +#include +#include +#include +#include +#include + +const QString PebbleFirmware::firmwareURL("http://pebblefw.s3.amazonaws.com/pebble/%1/%2/latest.json"); + +PebbleFirmware::PebbleFirmware(QObject *parent) : + QObject(parent), nm(new QNetworkAccessManager(this)) +{ + connect(nm, SIGNAL(finished(QNetworkReply*)), SLOT(onNetworkReplyFinished(QNetworkReply*))); +} + +void PebbleFirmware::updateLatest(QString hw) +{ + QNetworkRequest req; + req.setUrl(firmwareURL.arg(hw).arg("release-v2")); + req.setRawHeader("Cache-Control", "no-cache"); + nm->get(req); +} + +void PebbleFirmware::fetchFirmware(QString type) +{ + QNetworkRequest req; + req.setUrl(_latest.value(type).toObject().value("url").toString()); + req.setRawHeader("Cache-Control", "no-cache"); + nm->get(req); +} + +void PebbleFirmware::onNetworkReplyFinished(QNetworkReply* rep) +{ + qDebug() << "Download finished" << rep->url(); + + if (rep->request().url().toString().endsWith("/latest.json")) { + QJsonDocument jsonResponse = QJsonDocument::fromJson(rep->readAll()); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject.isEmpty()) { + qDebug() << "Latest firmware" << jsonObject; + _latest = jsonObject.value("normal").toObject(); + emit latestChanged(); + } + } else if (rep->url().toString().endsWith(".pbz")) { + QDir downDir(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)); + QFileInfo name(rep->url().toLocalFile()); + QFile file(downDir.absoluteFilePath(name.fileName())); + file.open(QIODevice::WriteOnly|QIODevice::Truncate); + if (file.write(rep->readAll()) == -1) { + qWarning() << "Error writing" << file.fileName() << file.errorString(); + } else { + file.close(); + qDebug() << "Downloaded" << file.fileName(); + emit firmwareFetched(file.fileName()); + } + } else { + qWarning() << "Unrequested download" << rep->request().url(); + } +} diff --git a/app/pebblefirmware.h b/app/pebblefirmware.h new file mode 100644 index 0000000..3890048 --- /dev/null +++ b/app/pebblefirmware.h @@ -0,0 +1,38 @@ +#ifndef PEBBLEFIRMWARE_H +#define PEBBLEFIRMWARE_H + +#include +#include +#include +#include + +class PebbleFirmware : public QObject +{ + Q_OBJECT + Q_PROPERTY(QJsonObject latest READ latest NOTIFY latestChanged) + + QJsonObject latest() { return _latest; } + +public: + explicit PebbleFirmware(QObject *parent = 0); + + const static QString firmwareURL; + +signals: + void latestChanged(); + void firmwareFetched(QString pbz); + +public slots: + void updateLatest(QString hw); + void fetchFirmware(QString type); + +private: + QJsonObject _latest; + + QNetworkAccessManager *nm; + +private slots: + void onNetworkReplyFinished(QNetworkReply*); +}; + +#endif // PEBBLEFIRMWARE_H diff --git a/app/qml/pages/ManagerPage.qml b/app/qml/pages/ManagerPage.qml index bfafeb5..894797d 100644 --- a/app/qml/pages/ManagerPage.qml +++ b/app/qml/pages/ManagerPage.qml @@ -1,34 +1,3 @@ -/* - Copyright (C) 2014 Jouni Roivas - Copyright (C) 2013 Jolla Ltd. - Contact: Thomas Perl - All rights reserved. - - You may use this file under the terms of BSD license as follows: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the authors nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - import QtQuick 2.0 import QtQml 2.1 import Sailfish.Silica 1.0 diff --git a/app/qml/pages/WatchInfo.qml b/app/qml/pages/WatchInfo.qml index 9ae1135..94445fb 100644 --- a/app/qml/pages/WatchInfo.qml +++ b/app/qml/pages/WatchInfo.qml @@ -5,19 +5,6 @@ import Sailfish.Silica 1.0 Page { id: watchInfoPage - property string firmwareVersion - property string recoveryVersion - - Component.onCompleted: { - pebbled.info.firmware.forEach(function(firmware){ - if (firmware.recovery) { - recoveryVersion = firmware.version - } else { - firmwareVersion = firmware.version - } - }) - } - Column { id: column width: watchInfoPage.width @@ -65,7 +52,7 @@ Page { text: qsTr("Firmware") } Label { - text: firmwareVersion + text: app.firmwareVersion } Label { @@ -73,8 +60,43 @@ Page { text: qsTr("Recovery") } Label { - text: recoveryVersion + text: app.recoveryVersion + } + } + + Label { + text: qsTr("Firmware") + font.family: Theme.fontFamilyHeading + color: Theme.highlightColor + anchors.right: parent.right + anchors.rightMargin: Theme.paddingMedium + } + Grid { + columns: 2 + spacing: Theme.paddingMedium + anchors { + left: parent.left + right: parent.right + margins: Theme.paddingLarge + } + + Label { + color: Theme.highlightColor + text: qsTr("Latest") + } + Label { + text: app.firmwareLatest || qsTr("unknown") + } + } + Button { + visible: app.firmwareLatest && app.firmwareVersion && app.firmwareVersion !== app.firmwareLatest + text: qsTr("Upgrade Firmware") + anchors { + left: parent.left + right: parent.right + margins: Theme.paddingLarge * 2 } + onClicked: pageStack.push(Qt.resolvedUrl("FirmwareUpgrade.qml")) } } } diff --git a/app/qml/pebble.qml b/app/qml/pebble.qml index 2e26ebe..a4b8b1f 100644 --- a/app/qml/pebble.qml +++ b/app/qml/pebble.qml @@ -1,34 +1,3 @@ -/* - Copyright (C) 2014 Jouni Roivas - Copyright (C) 2013 Jolla Ltd. - Contact: Thomas Perl - All rights reserved. - - You may use this file under the terms of BSD license as follows: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the authors nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - import QtQuick 2.0 import Sailfish.Silica 1.0 import "pages" @@ -36,6 +5,63 @@ import org.pebbled 0.1 ApplicationWindow { + id: app + + property string firmwareVersion + property string recoveryVersion + property string hardwareVersion + property string firmwareLatest + initialPage: Component { ManagerPage { } } cover: Qt.resolvedUrl("cover/CoverPage.qml") + + function parseInfo() { + if (pebbled.info.firmware && pebbled.info.firmware.length) { + pebbled.info.firmware.forEach(function(firmware){ + if (firmware.recovery) { + recoveryVersion = firmware.version + } else { + firmwareVersion = firmware.version + hardwareVersion = firmware.hardware + } + }) + } else { + firmwareVersion = recoveryVersion = hardwareVersion = "" + } + } + + function notifyNewFirmware() { + firmwareLatest = pebbleFirmware.latest.friendlyVersion || "" + if (firmwareLatest && firmwareVersion && firmwareVersion !== firmwareLatest) { + pebbled.notifyFirmware(firmwareLatest); + } + } + + Component.onCompleted: { + parseInfo() + } + + Connections { + target: pebbled + onInfoChanged: { + parseInfo() + } + } + + onHardwareVersionChanged: { + if (hardwareVersion) { + pebbleFirmware.updateLatest(hardwareVersion) + } + } + + onFirmwareVersionChanged: { + notifyNewFirmware() + } + + Connections { + target: pebbleFirmware + onLatestChanged: { + notifyNewFirmware() + } + } } diff --git a/app/translations/pebble-es.ts b/app/translations/pebble-es.ts index f93bc2b..013942e 100644 --- a/app/translations/pebble-es.ts +++ b/app/translations/pebble-es.ts @@ -133,154 +133,154 @@ ManagerPage - + Pebble Appstore - + About Acerca de - + Pebble Manager - + Waiting for watch... If it can't be found please check it's available and paired in Bluetooth settings. Buscando el reloj Si esto tarda mucho, comprueba que el reloj esté emparejado correctamente. - + Service Servicio - + Enabled Habilitado - + Automatic startup Inicio automático - + Manual startup Inicio manual - + Active Activo - + Running Ejecutándose - + Dead Detenido - + Connection Conexión - + Connected Conectado - + Disconnected Desconectado - + Settings Configuración - + Forward phone calls Transferir llamadas - + Silent when connected Modo silencio automático - + Sets phone profile to "silent" when Pebble is connected Activa el modo silencio cuando se conecte un Pebble - + Transliterate messages Transliterar mensajes - + Messages are transliterated to ASCII before sending to Pebble Codifica los mensajes entrates a ASCII antes de enviarlos a Pebble - + Notifications Notificaciones - + Messaging Mensajería - + SMS and IM SMS y chat - + Missed call Llamadas perdidas - + Emails Correos electrónicos - + Mitakuuluu - + Twitter Twitter - + Facebook Facebook - + Other notifications Resto de notificaciones - + All notifications Todas las notificaciones @@ -288,30 +288,46 @@ Si esto tarda mucho, comprueba que el reloj esté emparejado correctamente. WatchInfo - + Address - + Serial Number - + BootLoader - + + Firmware - + Recovery + + + Latest + + + + + unknown + + + + + Upgrade Firmware + + WatchPage diff --git a/app/translations/pebble-pl.ts b/app/translations/pebble-pl.ts index f61894b..0291ab8 100644 --- a/app/translations/pebble-pl.ts +++ b/app/translations/pebble-pl.ts @@ -129,154 +129,154 @@ ManagerPage - + Pebble Appstore Pebble Appstore - + About Informacje - + Pebble Manager Pebble Manager - + Waiting for watch... If it can't be found please check it's available and paired in Bluetooth settings. Oczekiwanie na zegarek... Jeśli nie zostaje znaleziony sprawdź czy jest w zasięgu i czy jest sparowany w ustawieniach Bluetooth. - + Service Usługa - + Enabled Włączona - + Automatic startup Start automatyczny - + Manual startup Start ręczny - + Active Aktywna - + Running Pracuje - + Dead Martwa - + Connection Połączenie - + Connected Połączony - + Disconnected Rozłączony - + Settings Ustawienia - + Forward phone calls Przekazuj telefony - + Silent when connected Cichy gdy połączony - + Sets phone profile to "silent" when Pebble is connected Ustawia "cichy" profil telefonu gdy Pebble jest połączony - + Transliterate messages Transliteracja wiadomości - + Messages are transliterated to ASCII before sending to Pebble Wiadomości są transliterowane do ASCII przed wysłaniem do Pebble - + Notifications Powiadomienia - + Messaging Wiadomości - + SMS and IM SMS i IM - + Missed call Ominięte telefony - + Emails Emaile - + Mitakuuluu Mitakuuluu - + Twitter Twitter - + Facebook Facebook - + Other notifications Pozostałe powiadomienia - + All notifications Wszystkie powiadomienia @@ -284,30 +284,46 @@ Jeśli nie zostaje znaleziony sprawdź czy jest w zasięgu i czy jest sparowany WatchInfo - + Address Adres - + Serial Number Numer seryjny - + BootLoader Program ładowania - + + Firmware Firmware - + Recovery Recovery + + + Latest + + + + + unknown + + + + + Upgrade Firmware + + WatchPage diff --git a/app/translations/pebble.ts b/app/translations/pebble.ts index 5cf9a4d..dcb9a34 100644 --- a/app/translations/pebble.ts +++ b/app/translations/pebble.ts @@ -129,153 +129,153 @@ ManagerPage - + Pebble Appstore - + About - + Pebble Manager - + Waiting for watch... If it can't be found please check it's available and paired in Bluetooth settings. - + Service - + Enabled - + Automatic startup - + Manual startup - + Active - + Running - + Dead - + Connection - + Connected - + Disconnected - + Settings - + Forward phone calls - + Silent when connected - + Sets phone profile to "silent" when Pebble is connected - + Transliterate messages - + Messages are transliterated to ASCII before sending to Pebble - + Notifications - + Messaging - + SMS and IM - + Missed call - + Emails - + Mitakuuluu - + Twitter - + Facebook - + Other notifications - + All notifications @@ -283,30 +283,46 @@ If it can't be found please check it's available and paired in Bluetoo WatchInfo - + Address - + Serial Number - + BootLoader - + + Firmware - + Recovery + + + Latest + + + + + unknown + + + + + Upgrade Firmware + + WatchPage diff --git a/daemon/daemon.pro b/daemon/daemon.pro index aca5597..35eb302 100644 --- a/daemon/daemon.pro +++ b/daemon/daemon.pro @@ -51,10 +51,7 @@ HEADERS += \ uploadmanager.h \ stm32crc.h -DBUS_ADAPTORS += ../org.pebbled.Watch.xml - -OTHER_FILES += $$DBUS_ADAPTORS \ - js/typedarray.js +OTHER_FILES += js/typedarray.js DEFINES += QUAZIP_STATIC include(quazip/quazip.pri) diff --git a/org.pebbled.Watch.xml b/org.pebbled.Watch.xml index f125b03..3eae1ab 100644 --- a/org.pebbled.Watch.xml +++ b/org.pebbled.Watch.xml @@ -70,5 +70,11 @@ + + + + + + diff --git a/pebble.pro b/pebble.pro index 1f8f90b..c46ed1a 100644 --- a/pebble.pro +++ b/pebble.pro @@ -1,6 +1,7 @@ TEMPLATE = subdirs SUBDIRS = daemon app OTHER_FILES += \ + org.pebbled.Watch.xml \ README.md \ rpm/pebble.spec \ rpm/pebble.yaml \ -- cgit v1.2.3