Skip to content

Commit

Permalink
Property API (#139)
Browse files Browse the repository at this point in the history
* Update protobuf definitions

* Add property messages to flipperproto0 and interface

* Add ProtobufVersion messages to flipperproto0 and interface

* Add ProtobufVersionOperation to backend rpc

* Add ProtobufVersion to MainResponse

* Improve protobuf version checking, make it unsigned

* Add device info via new PropertyGet API
  • Loading branch information
gsurkov authored Dec 8, 2022
1 parent c75ae5c commit ba67025
Show file tree
Hide file tree
Showing 34 changed files with 629 additions and 27 deletions.
4 changes: 4 additions & 0 deletions backend/backend.pro
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SOURCES += \
flipperzero/rpc/guistartvirtualdisplayoperation.cpp \
flipperzero/rpc/guistopscreenstreamoperation.cpp \
flipperzero/rpc/guistopvirtualdisplayoperation.cpp \
flipperzero/rpc/propertygetoperation.cpp \
flipperzero/rpc/startrpcoperation.cpp \
flipperzero/rpc/stoprpcoperation.cpp \
flipperzero/rpc/storageinfooperation.cpp \
Expand All @@ -43,6 +44,7 @@ SOURCES += \
flipperzero/rpc/systemdeviceinfooperation.cpp \
flipperzero/rpc/systemfactoryresetoperation.cpp \
flipperzero/rpc/systemgetdatetimeoperation.cpp \
flipperzero/rpc/systemprotobufversionoperation.cpp \
flipperzero/rpc/systemrebootoperation.cpp \
flipperzero/rpc/systemsetdatetimeoperation.cpp \
flipperzero/rpc/skipmotdoperation.cpp \
Expand Down Expand Up @@ -138,6 +140,7 @@ HEADERS += \
flipperzero/rpc/guistartvirtualdisplayoperation.h \
flipperzero/rpc/guistopscreenstreamoperation.h \
flipperzero/rpc/guistopvirtualdisplayoperation.h \
flipperzero/rpc/propertygetoperation.h \
flipperzero/rpc/startrpcoperation.h \
flipperzero/rpc/stoprpcoperation.h \
flipperzero/rpc/storageinfooperation.h \
Expand All @@ -151,6 +154,7 @@ HEADERS += \
flipperzero/rpc/systemdeviceinfooperation.h \
flipperzero/rpc/systemfactoryresetoperation.h \
flipperzero/rpc/systemgetdatetimeoperation.h \
flipperzero/rpc/systemprotobufversionoperation.h \
flipperzero/rpc/systemrebootoperation.h \
flipperzero/rpc/systemsetdatetimeoperation.h \
flipperzero/rpc/skipmotdoperation.h \
Expand Down
4 changes: 2 additions & 2 deletions backend/flipperzero/deviceinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ struct StorageInfo {

struct ProtobufInfo {
public:
int versionMajor;
int versionMinor;
uint32_t versionMajor;
uint32_t versionMinor;
};

struct DeviceInfo {
Expand Down
94 changes: 89 additions & 5 deletions backend/flipperzero/helper/deviceinfohelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
#include "flipperzero/rpc/stoprpcoperation.h"
#include "flipperzero/rpc/storageinfooperation.h"
#include "flipperzero/rpc/storagestatoperation.h"
#include "flipperzero/rpc/propertygetoperation.h"
#include "flipperzero/rpc/systemdeviceinfooperation.h"
#include "flipperzero/rpc/systemgetdatetimeoperation.h"
#include "flipperzero/rpc/systemsetdatetimeoperation.h"
#include "flipperzero/rpc/systemprotobufversionoperation.h"

#include "device/stm32wb55.h"
#include "serialfinder.h"
Expand Down Expand Up @@ -70,6 +72,10 @@ void VCPDeviceInfoHelper::nextStateLogic()
startRPCSession();

} else if(state() == VCPDeviceInfoHelper::StartingRPCSession) {
setState(VCPDeviceInfoHelper::FetchingProtobufVersion);
fetchProtobufVersion();

} else if(state() == VCPDeviceInfoHelper::FetchingProtobufVersion) {
setState(VCPDeviceInfoHelper::FetchingDeviceInfo);
fetchDeviceInfo();

Expand Down Expand Up @@ -120,7 +126,39 @@ void VCPDeviceInfoHelper::startRPCSession()
m_rpc->startSession();
}

void VCPDeviceInfoHelper::fetchProtobufVersion()
{
auto *operation = m_rpc->systemProtobufVersion();

connect(operation, &AbstractOperation::finished, this, [=]() {
if(operation->isError()) {
finishWithError(BackendError::InvalidDevice, QStringLiteral("Failed to get protobuf version: %1").arg(operation->errorString()));
return;
}

m_deviceInfo.protobuf = {
operation->versionMajor(),
operation->versionMinor()
};

qCDebug(CATEGORY_DEBUG).noquote() << QStringLiteral("Detected protobuf version: %1.%2").arg(operation->versionMajor()).arg(operation->versionMinor());

advanceState();
});
}

void VCPDeviceInfoHelper::fetchDeviceInfo()
{
const auto &protobuf = m_deviceInfo.protobuf;

if((protobuf.versionMajor > 0) || (protobuf.versionMinor >= 14)) {
fetchDeviceInfoProperty();
} else {
fetchDeviceInfoLegacy();
}
}

void VCPDeviceInfoHelper::fetchDeviceInfoLegacy()
{
auto *operation = m_rpc->systemDeviceInfo();

Expand Down Expand Up @@ -149,11 +187,6 @@ void VCPDeviceInfoHelper::fetchDeviceInfo()
(Region)operation->value(QByteArrayLiteral("hardware_region")).toInt(),
};

m_deviceInfo.protobuf = {
operation->value(QByteArrayLiteral("protobuf_version_major")).toInt(),
operation->value(QByteArrayLiteral("protobuf_version_minor")).toInt()
};

if(operation->value(QByteArrayLiteral("radio_alive")) == QByteArrayLiteral("true")) {
m_deviceInfo.fusVersion = QStringLiteral("%1.%2.%3").arg(
operation->value(QByteArrayLiteral("radio_fus_major")),
Expand All @@ -176,6 +209,57 @@ void VCPDeviceInfoHelper::fetchDeviceInfo()
});
}

void VCPDeviceInfoHelper::fetchDeviceInfoProperty()
{
auto *operation = m_rpc->propertyGet(QByteArrayLiteral("devinfo"));

connect(operation, &AbstractOperation::finished, this, [=]() {
if(operation->isError()) {
finishWithError(BackendError::InvalidDevice, QStringLiteral("Failed to get device information: %1").arg(operation->errorString()));
return;
}

m_deviceInfo.name = operation->value(QByteArrayLiteral("hardware.name"));

m_deviceInfo.firmware = {
operation->value(QByteArrayLiteral("firmware.version")),
operation->value(QByteArrayLiteral("firmware.commit.hash")),
operation->value(QByteArrayLiteral("firmware.branch.name")),
branchToChannelName(operation->value(QByteArrayLiteral("firmware.branch.name"))),
QDateTime::fromString(operation->value(QByteArrayLiteral("firmware.build.date")), "dd-MM-yyyy").date()
};

m_deviceInfo.hardware = {
operation->value(QByteArrayLiteral("hardware.ver")),
QByteArrayLiteral("f") + operation->value(QByteArrayLiteral("hardware.target")),
QByteArrayLiteral("b") + operation->value(QByteArrayLiteral("hardware.body")),
QByteArrayLiteral("c") + operation->value(QByteArrayLiteral("hardware.connect")),
(Color)operation->value(QByteArrayLiteral("hardware.color")).toInt(),
(Region)operation->value(QByteArrayLiteral("hardware.region.builtin")).toInt(),
};

if(operation->value(QByteArrayLiteral("radio.alive")) == QByteArrayLiteral("true")) {
m_deviceInfo.fusVersion = QStringLiteral("%1.%2.%3").arg(
operation->value(QByteArrayLiteral("radio.fus.major")),
operation->value(QByteArrayLiteral("radio.fus.minor")),
operation->value(QByteArrayLiteral("radio.fus.sub")));

m_deviceInfo.radioVersion = QStringLiteral("%1.%2.%3").arg(
operation->value(QByteArrayLiteral("radio.stack.major")),
operation->value(QByteArrayLiteral("radio.stack.minor")),
operation->value(QByteArrayLiteral("radio.stack.sub")));

m_deviceInfo.stackType = operation->value(QByteArrayLiteral("radio.stack.type")).toInt();
}

if(m_deviceInfo.name.isEmpty()) {
finishWithError(BackendError::InvalidDevice, QStringLiteral("Failed to read device information: required fields are not present"));
} else {
advanceState();
}
});
}

void VCPDeviceInfoHelper::checkSDCard()
{
auto *operation = m_rpc->storageInfo(QByteArrayLiteral("/ext"));
Expand Down
4 changes: 4 additions & 0 deletions backend/flipperzero/helper/deviceinfohelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class VCPDeviceInfoHelper : public AbstractDeviceInfoHelper
enum OperationState {
FindingSerialPort = AbstractOperationHelper::User,
StartingRPCSession,
FetchingProtobufVersion,
FetchingDeviceInfo,
CheckingSDCard,
CheckingManifest,
Expand All @@ -52,7 +53,10 @@ class VCPDeviceInfoHelper : public AbstractDeviceInfoHelper

void findSerialPort();
void startRPCSession();
void fetchProtobufVersion();
void fetchDeviceInfo();
void fetchDeviceInfoLegacy();
void fetchDeviceInfoProperty();
void checkSDCard();
void checkManifest();
void getTimeSkew();
Expand Down
21 changes: 17 additions & 4 deletions backend/flipperzero/protobufsession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "rpc/systemsetdatetimeoperation.h"
#include "rpc/systemfactoryresetoperation.h"
#include "rpc/systemupdateoperation.h"
#include "rpc/systemprotobufversionoperation.h"

#include "rpc/guisendinputoperation.h"
#include "rpc/guiscreenframeoperation.h"
Expand All @@ -36,6 +37,8 @@
#include "rpc/guistartvirtualdisplayoperation.h"
#include "rpc/guistopvirtualdisplayoperation.h"

#include "rpc/propertygetoperation.h"

#if defined(QT_STATIC)
Q_IMPORT_PLUGIN(ProtobufPlugin)
#endif
Expand Down Expand Up @@ -135,6 +138,11 @@ SystemUpdateOperation *ProtobufSession::systemUpdate(const QByteArray &manifestP
return enqueueOperation(new SystemUpdateOperation(getAndIncrementCounter(), manifestPath, this));
}

SystemProtobufVersionOperation *ProtobufSession::systemProtobufVersion()
{
return enqueueOperation(new SystemProtobufVersionOperation(getAndIncrementCounter(), this));
}

StorageListOperation *ProtobufSession::storageList(const QByteArray &path)
{
return enqueueOperation(new StorageListOperation(getAndIncrementCounter(), path, this));
Expand Down Expand Up @@ -205,6 +213,11 @@ GuiScreenFrameOperation *ProtobufSession::guiSendScreenFrame(const QByteArray &s
return enqueueOperation(new GuiScreenFrameOperation(getAndIncrementCounter(), screenData, this));
}

PropertyGetOperation *ProtobufSession::propertyGet(const QByteArray &key)
{
return enqueueOperation(new PropertyGetOperation(getAndIncrementCounter(), key, this));
}

void ProtobufSession::startSession()
{
if(m_sessionState != Stopped) {
Expand Down Expand Up @@ -420,7 +433,7 @@ void ProtobufSession::setSessionState(SessionState newState)
}

#if !defined(QT_STATIC)
const QString ProtobufSession::protobufPluginFileName(int versionMajor)
const QString ProtobufSession::protobufPluginFileName(uint32_t versionMajor)
{
#if defined(Q_OS_WINDOWS)
return QStringLiteral("flipperproto%1.dll").arg(versionMajor);
Expand All @@ -434,9 +447,9 @@ const QString ProtobufSession::protobufPluginFileName(int versionMajor)
}
#endif

QVector<int> ProtobufSession::supportedProtobufVersions()
QVector<uint32_t> ProtobufSession::supportedProtobufVersions()
{
QVector<int> ret;
QVector<uint32_t> ret;

#if defined(QT_STATIC)
const auto staticInstances = QPluginLoader::staticInstances();
Expand All @@ -451,7 +464,7 @@ QVector<int> ProtobufSession::supportedProtobufVersions()
#else
const auto libraryPaths = QCoreApplication::libraryPaths();

for(auto i = 0;; ++i) {
for(uint32_t i = 0;; ++i) {
for(const auto &path : libraryPaths) {
const QDir libraryDir(path);

Expand Down
15 changes: 10 additions & 5 deletions backend/flipperzero/protobufsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class SystemGetDateTimeOperation;
class SystemSetDateTimeOperation;
class SystemFactoryResetOperation;
class SystemUpdateOperation;
class SystemProtobufVersionOperation;

class StorageListOperation;
class StorageInfoOperation;
Expand All @@ -38,6 +39,8 @@ class GuiSendInputOperation;
class GuiStartVirtualDisplayOperation;
class GuiStopVirtualDisplayOperation;

class PropertyGetOperation;

class ProtobufSession : public QObject, public Failable
{
Q_OBJECT
Expand Down Expand Up @@ -71,6 +74,7 @@ class ProtobufSession : public QObject, public Failable
SystemFactoryResetOperation *factoryReset();
SystemDeviceInfoOperation *systemDeviceInfo();
SystemUpdateOperation *systemUpdate(const QByteArray &manifestPath);
SystemProtobufVersionOperation *systemProtobufVersion();

StorageListOperation *storageList(const QByteArray &path);
StorageInfoOperation *storageInfo(const QByteArray &path);
Expand All @@ -88,6 +92,8 @@ class ProtobufSession : public QObject, public Failable
GuiSendInputOperation *guiSendInput(int key, int type);
GuiScreenFrameOperation *guiSendScreenFrame(const QByteArray &screenData);

PropertyGetOperation *propertyGet(const QByteArray &key);

signals:
void sessionStateChanged();
void broadcastResponseReceived(QObject *response);
Expand All @@ -109,9 +115,9 @@ private slots:

private:
#if !defined(QT_STATIC)
static const QString protobufPluginFileName(int versionMajor);
static const QString protobufPluginFileName(uint32_t versionMajor);
#endif
static QVector<int> supportedProtobufVersions();
static QVector<uint32_t> supportedProtobufVersions();

void setSessionState(SessionState newState);

Expand Down Expand Up @@ -147,9 +153,8 @@ private slots:

qint64 m_bytesToWrite;
uint32_t m_counter;

int m_versionMajor;
int m_versionMinor;
uint32_t m_versionMajor;
uint32_t m_versionMinor;
};

}
Expand Down
40 changes: 40 additions & 0 deletions backend/flipperzero/rpc/propertygetoperation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "propertygetoperation.h"

#include "protobufplugininterface.h"
#include "mainresponseinterface.h"
#include "propertyresponseinterface.h"

using namespace Flipper;
using namespace Zero;

PropertyGetOperation::PropertyGetOperation(uint32_t id, const QByteArray &key, QObject *parent):
AbstractProtobufOperation(id, parent),
m_key(key)
{}

const QString PropertyGetOperation::description() const
{
return QStringLiteral("Property Get");
}

const QByteArray PropertyGetOperation::value(const QByteArray &key) const
{
return m_data.value(key);
}

const QByteArray PropertyGetOperation::encodeRequest(ProtobufPluginInterface *encoder)
{
return encoder->propertyGet(id(), m_key);
}

bool PropertyGetOperation::processResponse(QObject *response)
{
const auto *msg = qobject_cast<PropertyGetResponseInterface*>(response);

if(msg) {
m_data.insert(msg->key(), msg->value());
return true;
}

return qobject_cast<EmptyResponseInterface*>(response);
}
31 changes: 31 additions & 0 deletions backend/flipperzero/rpc/propertygetoperation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "abstractprotobufoperation.h"

#include <QHash>
#include <QByteArray>

namespace Flipper {
namespace Zero {

class PropertyGetOperation : public AbstractProtobufOperation
{
Q_OBJECT

public:
PropertyGetOperation(uint32_t id, const QByteArray &key, QObject *parent = nullptr);
const QString description() const override;
const QByteArray value(const QByteArray &key) const;

const QByteArray encodeRequest(ProtobufPluginInterface *encoder) override;

private:
bool processResponse(QObject *response) override;

QByteArray m_key;
QHash<QByteArray, QByteArray> m_data;
};

}
}

Loading

0 comments on commit ba67025

Please sign in to comment.