Skip to content
This repository was archived by the owner on Jan 28, 2022. It is now read-only.

Commit 552a10e

Browse files
authored
feat: reset remote to defaults with button press on boot (#481)
Pressing and holding `volume up`, `top left button (circle)` and `dpad down` on boot will reset the configuration file to default and create a marker file for first time setup. The remote will reboot. **How to reset the remote to factory defaults:** Press and hold: `volume up`, `top left` and `dpad down` buttons while turning on the remote. When the remote reboots, immediately release these buttons The remote will start up with the setup wizard
1 parent 54846ba commit 552a10e

File tree

8 files changed

+88
-12
lines changed

8 files changed

+88
-12
lines changed

remote.pro

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#############################################################################/
2323

2424
QT += qml quick websockets quickcontrols2 bluetooth
25-
CONFIG += c++14 disable-desktop
25+
CONFIG += c++17 disable-desktop
2626
#disable qtquickcompiler for QML debugging!
2727
CONFIG += qtquickcompiler
2828

@@ -255,8 +255,10 @@ linux {
255255
sources/hardware/linux/arm/displaycontrol_yio.cpp \
256256
sources/hardware/linux/arm/drv2605.cpp \
257257
sources/hardware/linux/arm/mcp23017_interrupt.cpp
258-
}
259258

259+
# needed for std::filesystem
260+
LIBS += -lstdc++fs
261+
}
260262
}
261263

262264
# Android specific files (empty template for now)

sources/hardware/buttonhandler.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ static Q_LOGGING_CATEGORY(CLASS_LC, "hw.buttonhandler");
3030
ButtonHandler *ButtonHandler::s_instance = nullptr;
3131

3232
ButtonHandler::ButtonHandler(InterruptHandler *interruptHandler, YioAPI *api, QObject *parent)
33-
: QObject(parent), m_itnerruptHandler(interruptHandler), m_api(api) {
33+
: QObject(parent), m_itnerruptHandler(interruptHandler), m_api(api), m_resetButtonsPressed(false) {
3434
s_instance = this;
3535

3636
// connect to interrupt handler
3737
connect(m_itnerruptHandler, &InterruptHandler::interruptEvent, this, &ButtonHandler::onInterrupt);
38+
m_resetButtonsPressed = m_itnerruptHandler->m_wasResetPress;
3839

3940
// connect to API
4041
connect(m_api, &YioAPI::buttonPressed, this, &ButtonHandler::onYIOAPIPressed);

sources/hardware/buttonhandler.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class ButtonHandler : public QObject {
6565
explicit ButtonHandler(InterruptHandler* interruptHandler, YioAPI* api, QObject* parent = nullptr);
6666
virtual ~ButtonHandler();
6767

68+
bool resetButtonsPressed() { return m_resetButtonsPressed; }
69+
6870
static ButtonHandler* getInstance() { return s_instance; }
6971
static QObject* getQMLInstance(QQmlEngine* engine, QJSEngine* scriptEngine);
7072

@@ -76,9 +78,7 @@ class ButtonHandler : public QObject {
7678
static ButtonHandler* s_instance;
7779
InterruptHandler* m_itnerruptHandler;
7880
YioAPI* m_api;
79-
80-
int m_buttonPressed = -1;
81-
int m_buttonReleased = -1;
81+
bool m_resetButtonsPressed;
8282

8383
private slots: // NOLINT open issue: https://github.com/cpplint/cpplint/pull/99
8484
void onInterrupt(int event);

sources/hardware/interrupthandler.h

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class InterruptHandler : public Device {
6565

6666
Q_INVOKABLE virtual void shutdown() = 0;
6767

68+
bool m_wasResetPress = false;
69+
6870
signals:
6971
void interruptEvent(int event);
7072

sources/hardware/linux/arm/mcp23017_handler.h

+14-4
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@
2222

2323
#pragma once
2424

25-
#include <QLoggingCategory>
26-
#include <QString>
27-
#include <QtDebug>
28-
2925
#include <stdbool.h>
3026
#include <stdint.h>
3127
#include <time.h>
3228
#include <unistd.h>
3329
#include <wiringPi.h>
3430
#include <wiringPiI2C.h>
3531

32+
#include <QLoggingCategory>
33+
#include <QString>
34+
#include <QtDebug>
35+
3636
#include "../../interrupthandler.h"
3737

3838
#define MCP23017_ADDRESS 0x20
@@ -122,6 +122,16 @@ class MCP23017 {
122122
return true;
123123
}
124124

125+
bool readReset() {
126+
// read initial state to determine if reset is needed
127+
int gpioB = wiringPiI2CReadReg8(m_i2cFd, MCP23017_GPIOB);
128+
if (!(gpioB & 0x040) && !(gpioB & 0x080) && !(gpioB & 0x04)) {
129+
return true;
130+
} else {
131+
return false;
132+
}
133+
}
134+
125135
int readInterrupt() {
126136
int intfA = wiringPiI2CReadReg8(m_i2cFd, MCP23017_INTFA);
127137
int gpioA = wiringPiI2CReadReg8(m_i2cFd, MCP23017_GPIOA);

sources/hardware/linux/arm/mcp23017_interrupt.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ bool Mcp23017InterruptHandler::setupGPIO() {
102102
notifier->addPath(m_gpioValueDevice);
103103
connect(notifier, &QFileSystemWatcher::fileChanged, this, &Mcp23017InterruptHandler::interruptHandler);
104104

105+
if (mcp.readReset()) {
106+
m_wasResetPress = true;
107+
}
108+
105109
return true;
106110
}
107111

sources/main.cpp

+46-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
#include <QQmlContext>
3131
#include <QQuickWindow>
3232
#include <QtDebug>
33+
#if defined(Q_PROCESSOR_ARM)
34+
#include <filesystem>
35+
#endif
3336

3437
#include "bluetooth.h"
3538
#include "commandlinehandler.h"
@@ -94,8 +97,8 @@ int main(int argc, char* argv[]) {
9497
bool configError = false;
9598
if (!QFile::exists(cmdLineHandler.configFile())) {
9699
qFatal("App configuration file not found: %s", cmdLineHandler.configFile().toLatin1().constData());
97-
return 1;
98100
}
101+
99102
Config* config = new Config(&engine, cmdLineHandler.configFile(), cmdLineHandler.configSchemaFile(), appPath);
100103
if (!config->readConfig()) {
101104
qCCritical(CLASS_LC).noquote() << "Invalid configuration!" << endl << config->getError();
@@ -207,6 +210,47 @@ int main(int argc, char* argv[]) {
207210
ButtonHandler* buttonHandler = new ButtonHandler(hwFactory->getInterruptHandler(), yioapi);
208211
qmlRegisterSingletonType<ButtonHandler>("ButtonHandler", 1, 0, "ButtonHandler", &ButtonHandler::getQMLInstance);
209212

213+
#if defined(Q_PROCESSOR_ARM)
214+
// reset combination was pressed on startup (only on the remote hardware)
215+
if (buttonHandler->resetButtonsPressed()) {
216+
QString defaultConfigPath = qEnvironmentVariable(Environment::ENV_YIO_APP_DIR, appPath) + "/config.json";
217+
218+
if (QFile::exists(defaultConfigPath)) {
219+
// create marker file
220+
QFile file("/firstrun");
221+
if (file.open(QIODevice::WriteOnly)) {
222+
file.close();
223+
224+
// make a copy of existing configuration
225+
if (!std::filesystem::copy_file("/boot/config.json", "/boot/config.json.old",
226+
std::filesystem::copy_options::overwrite_existing)) {
227+
qCCritical(CLASS_LC) << "Error backing up existing configuration.";
228+
} else {
229+
if (!std::filesystem::copy_file(defaultConfigPath.toStdString(), "/boot/config.json",
230+
std::filesystem::copy_options::overwrite_existing)) {
231+
qCCritical(CLASS_LC) << "Error copying default configuration.";
232+
} else {
233+
// reset wifi settings
234+
wifiControl->clearConfiguredNetworks();
235+
236+
// reboot
237+
Launcher().launch("reboot");
238+
239+
return -1;
240+
}
241+
}
242+
} else {
243+
qCCritical(CLASS_LC) << "Error writing firstrun marker file";
244+
notifications.add(
245+
true, QGuiApplication::tr("An error occured while restoring to defaults. Please try again."));
246+
}
247+
} else {
248+
qCCritical(CLASS_LC) << "Default config file not found. Cannot restore to defaults.";
249+
notifications.add(true, QGuiApplication::tr("Default config file not found. Cannot restore to defaults."));
250+
}
251+
}
252+
#endif
253+
210254
// STANDBY CONTROL
211255
StandbyControl* standbyControl =
212256
new StandbyControl(displayControl, hwFactory->getProximitySensor(), hwFactory->getLightSensor(),
@@ -216,7 +260,7 @@ int main(int argc, char* argv[]) {
216260
qmlRegisterSingletonType<StandbyControl>("StandbyControl", 1, 0, "StandbyControl", &StandbyControl::getQMLInstance);
217261

218262
// SOFTWARE UPDATE
219-
QVariantMap appUpdCfg = config->getSettings().value("softwareupdate").toMap();
263+
QVariantMap appUpdCfg = config->getSettings().value("softwareupdate").toMap();
220264
SoftwareUpdate* softwareUpdate = new SoftwareUpdate(appUpdCfg, hwFactory->getBatteryFuelGauge());
221265
qmlRegisterSingletonType<SoftwareUpdate>("SoftwareUpdate", 1, 0, "SoftwareUpdate", &SoftwareUpdate::getQMLInstance);
222266

translations/en_US.ts

+13
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,19 @@ to set up YIO remote</source>
710710
<translation type="unfinished"></translation>
711711
</message>
712712
</context>
713+
<context>
714+
<name>QGuiApplication</name>
715+
<message>
716+
<location filename="../sources/main.cpp" line="242"/>
717+
<source>An error occured while restoring to defaults. Please try again.</source>
718+
<translation type="unfinished"></translation>
719+
</message>
720+
<message>
721+
<location filename="../sources/main.cpp" line="246"/>
722+
<source>Default config file not found. Cannot restore to defaults.</source>
723+
<translation type="unfinished"></translation>
724+
</message>
725+
</context>
713726
<context>
714727
<name>QObject</name>
715728
<message>

0 commit comments

Comments
 (0)