This commit is contained in:
Jens Noack 2020-10-17 23:19:33 +02:00
commit a21f06cb37
30 changed files with 955 additions and 208 deletions

View file

@ -1,4 +1,4 @@
QT += quick bluetooth QT += quick bluetooth quickcontrols2
CONFIG += c++11 CONFIG += c++11
TARGET = OmobiDisplayApp TARGET = OmobiDisplayApp
@ -20,7 +20,11 @@ HEADERS += \
RESOURCES += \ RESOURCES += \
ressources/qml/qml.qrc \ ressources/qml/qml.qrc \
ressources/shared/shared.qrc ressources/shared/shared.qrc \
ressources/translations/translations.qrc
TRANSLATIONS += \
ressources/translations/de.ts
# Additional import path used to resolve QML modules in Qt Creator's code model # Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH = QML_IMPORT_PATH =

@ -1 +1 @@
Subproject commit 76e457593e889885fd410fdbcdd659706a1eceb8 Subproject commit 534277a19867f2e41a2699fc863e1cae48dee741

View file

@ -1,7 +1,8 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQuickStyle> #include <QQuickStyle>
#include <qbluetoothleuart.h> #include <qbluetoothleuartclient.h>
#include <QTranslator>
#include "omobidisplaybackend.h" #include "omobidisplaybackend.h"
#include "omobidisplaytextmodel.h" #include "omobidisplaytextmodel.h"
@ -12,9 +13,14 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QTranslator translator;
translator.load(":/" + QLocale::system().name() + ".qm");
translator.load(":/de.qm");
app.installTranslator(&translator);
qmlRegisterType<OmobiDisplayBackend>("de.itsblue.omobidisplayapp", 1, 0, "OmobiDisplayBackend"); qmlRegisterType<OmobiDisplayBackend>("de.itsblue.omobidisplayapp", 1, 0, "OmobiDisplayBackend");
qmlRegisterUncreatableType<OmobiDisplayTextModel>("de.itsblue.omobidisplayapp", 1, 0, "OmobiDisplayTextModel", "OmobiDisplayTextModel cannot be created"); qmlRegisterUncreatableType<OmobiDisplayTextModel>("de.itsblue.omobidisplayapp", 1, 0, "OmobiDisplayTextModel", "OmobiDisplayTextModel cannot be created");
QBluetoothLeUart::init(); QBluetoothLeUartClient::init();
QQuickStyle::setStyle("Material"); QQuickStyle::setStyle("Material");

View file

@ -2,8 +2,8 @@
OmobiDisplayBackend::OmobiDisplayBackend(QObject *parent) : QObject(parent) OmobiDisplayBackend::OmobiDisplayBackend(QObject *parent) : QObject(parent)
{ {
this->ble = new QBluetoothLeUart(); this->bleClient = new QBluetoothLeUartClient();
this->ble->setUUIDs("92fecb20-1406-426a-afa5-cd5c1f306462", "92fecb21-1406-426a-afa5-cd5c1f306462", "92fecb22-1406-426a-afa5-cd5c1f306462"); this->bleClient->setUUIDs("92fecb20-1406-426a-afa5-cd5c1f306462", "92fecb21-1406-426a-afa5-cd5c1f306462", "92fecb22-1406-426a-afa5-cd5c1f306462");
this->displayTextModel = new OmobiDisplayTextModel(this); this->displayTextModel = new OmobiDisplayTextModel(this);
this->textSetsBuffer.clear(); this->textSetsBuffer.clear();
this->displayBrightness = -1; this->displayBrightness = -1;
@ -14,72 +14,74 @@ OmobiDisplayBackend::OmobiDisplayBackend(QObject *parent) : QObject(parent)
this->keepAliveTimer->setSingleShot(false); this->keepAliveTimer->setSingleShot(false);
connect(this->keepAliveTimer, &QTimer::timeout, this, &OmobiDisplayBackend::sendBluetoothKeepAlive); connect(this->keepAliveTimer, &QTimer::timeout, this, &OmobiDisplayBackend::sendBluetoothKeepAlive);
connect(this->ble, &QBluetoothLeUart::stateChanged, this, &OmobiDisplayBackend::handleBluetoothStateChange); connect(this->bleClient, &QBluetoothLeUartClient::stateChanged, this, &OmobiDisplayBackend::handleBluetoothStateChange);
connect(this->ble, &QBluetoothLeUart::foundNewDevice, this, &OmobiDisplayBackend::handleFoundNewDevice); connect(this->bleClient, &QBluetoothLeUartClient::foundNewDevice, this, &OmobiDisplayBackend::handleFoundNewDevice);
connect(this->ble, &QBluetoothLeUart::dataReceived, this, &OmobiDisplayBackend::handleBluetoothDataReceived); connect(this->bleClient, &QBluetoothLeUartClient::dataReceived, this, &OmobiDisplayBackend::handleBluetoothDataReceived);
connect(this->ble, &QBluetoothLeUart::connectedToDevice, this, &OmobiDisplayBackend::handleBluetoothDeviceConected); connect(this->bleClient, &QBluetoothLeUartClient::connectedToDevice, this, &OmobiDisplayBackend::handleBluetoothDeviceConected);
connect(this->displayTextModel, &OmobiDisplayTextModel::dataChanged, this, &OmobiDisplayBackend::handleDisplayTextModelDataChanged); connect(this->displayTextModel, &OmobiDisplayTextModel::dataChanged, this, &OmobiDisplayBackend::handleDisplayTextModelDataChanged);
connect(this->displayTextModel, &OmobiDisplayTextModel::rowsInserted, this, &OmobiDisplayBackend::handleDisplayTextModelRowsInserted); connect(this->displayTextModel, &OmobiDisplayTextModel::rowsInserted, this, &OmobiDisplayBackend::handleDisplayTextModelRowsInserted);
connect(this->displayTextModel, &OmobiDisplayTextModel::rowsRemoved, this, &OmobiDisplayBackend::handleDisplayTextModelRowsRemoved); connect(this->displayTextModel, &OmobiDisplayTextModel::rowsRemoved, this, &OmobiDisplayBackend::handleDisplayTextModelRowsRemoved);
this->setState(Idle); this->setState(Idle);
this->ble->startScanningForDevices(); this->bleClient->startScanningForDevices();
qDebug() << QCryptographicHash::hash("HalloTest", QCryptographicHash::Sha256).toHex();
// dd86fcfda3a20cbb8fbb3026a84550e0d70c2c79e7e8e36d6ffa04b9eef0401f
// dd86fcfda3a20cbb8fbb3026a84550e0d70c2c79e7e8e36d6ffa04b9eef0401f
} }
void OmobiDisplayBackend::startScanning() { void OmobiDisplayBackend::startScanning() {
this->ble->startScanningForDevices(); this->bleClient->startScanningForDevices();
} }
void OmobiDisplayBackend::handleBluetoothStateChange(QBluetoothLeUart::BluetoothLeUartState state){ void OmobiDisplayBackend::authenticate(QString code) {
// tell display to send over existing model data
this->setState(Authenticating);
QString combinedCode = this->bleClient->getCurrentDevice()->getAddress().toUpper() + code;
QString secret = QCryptographicHash::hash(combinedCode.toUtf8(), QCryptographicHash::Sha256).toHex();
this->sendBluetoothCommand(AuthorizeSessionCommand, QVariantMap{{"secret", secret}});
}
void OmobiDisplayBackend::handleBluetoothStateChange(QBluetoothLeUartClient::BluetoothLeUartClientState state){
switch(state){ switch(state){
case QBluetoothLeUart::Idle: { case QBluetoothLeUartClient::Idle: {
this->setState(Idle); this->setState(Idle);
break; break;
} }
case QBluetoothLeUart::Scanning: { case QBluetoothLeUartClient::Scanning: {
this->setState(Scanning); this->setState(Scanning);
break; break;
} }
case QBluetoothLeUart::ScanFinished: { case QBluetoothLeUartClient::ScanFinished: {
this->setState(ReadyToConnect); this->setState(ReadyToConnect);
break; break;
} }
case QBluetoothLeUart::Connecting: { case QBluetoothLeUartClient::Connecting: {
this->setState(Connecting); this->setState(Connecting);
break; break;
} }
case QBluetoothLeUart::ScanningForService: { case QBluetoothLeUartClient::ScanningForService: {
this->setState(Connecting); this->setState(Connecting);
break; break;
} }
case QBluetoothLeUart::ServiceFound: { case QBluetoothLeUartClient::ServiceFound: {
this->setState(Connecting); this->setState(Connecting);
break; break;
} }
case QBluetoothLeUart::Connected: case QBluetoothLeUartClient::Connected:
{ {
break; break;
} }
} }
if(state == QBluetoothLeUart::Connected) if(state == QBluetoothLeUartClient::Connected)
this->keepAliveTimer->start(); this->keepAliveTimer->start();
else if(this->keepAliveTimer->isActive()) else if(this->keepAliveTimer->isActive())
this->keepAliveTimer->stop(); this->keepAliveTimer->stop();
} }
void OmobiDisplayBackend::handleBluetoothDeviceConected() { void OmobiDisplayBackend::handleBluetoothDeviceConected() {
this->setState(Initing); this->setState(AuthenticationRequired);
this->authenticate("1234");
// tell display to send over existing model data // TODO: stuff
this->sendBluetoothCommand(AuthorizeSessionCommand, QVariantMap{{"secret", QCryptographicHash::hash("1234", QCryptographicHash::Sha256).toHex()}});
this->sendBluetoothCommand(GetAllTextSetsCommand);
this->sendBluetoothCommand(GetDisplayBrightnessCommand);
} }
void OmobiDisplayBackend::handleFoundNewDevice(QBluetoothLeUartDevice* device) { void OmobiDisplayBackend::handleFoundNewDevice(QBluetoothLeUartDevice* device) {
@ -123,7 +125,7 @@ void OmobiDisplayBackend::sendBluetoothCommand(OmobiDisplayCommand command, QVar
if(this->state == Connected) if(this->state == Connected)
this->setState(Loading); this->setState(Loading);
this->ble->sendData(doc.toJson(QJsonDocument::Compact)); this->bleClient->sendData(doc.toJson(QJsonDocument::Compact));
} }
void OmobiDisplayBackend::sendBluetoothKeepAlive() { void OmobiDisplayBackend::sendBluetoothKeepAlive() {
@ -131,7 +133,7 @@ void OmobiDisplayBackend::sendBluetoothKeepAlive() {
qDebug() << "Sending keep alive: \n" << qPrintable(doc.toJson(QJsonDocument::Indented)); qDebug() << "Sending keep alive: \n" << qPrintable(doc.toJson(QJsonDocument::Indented));
this->ble->sendData(doc.toJson(QJsonDocument::Compact)); this->bleClient->sendData(doc.toJson(QJsonDocument::Compact));
} }
void OmobiDisplayBackend::handleBluetoothDataReceived(QString s){ void OmobiDisplayBackend::handleBluetoothDataReceived(QString s){
@ -149,8 +151,16 @@ void OmobiDisplayBackend::handleBluetoothDataReceived(QString s){
switch (header) { switch (header) {
case AuthorizeSessionCommand: { case AuthorizeSessionCommand: {
// TODO: handle error if(status != Success) {
this->refreshLoadingState(); this->setState(AuthenticationRequired);
return;
}
this->waitingCommands = 0;
this->setState(Initing);
this->sendBluetoothCommand(GetAllTextSetsCommand);
this->sendBluetoothCommand(GetDisplayBrightnessCommand);
break; break;
} }
case KeepAliveCommand: { case KeepAliveCommand: {
@ -200,16 +210,14 @@ void OmobiDisplayBackend::handleBluetoothDataReceived(QString s){
this->refreshLoadingState(); this->refreshLoadingState();
break; break;
} }
case SetTextSetParameterCommand: { case SetTextSetParameterCommand:
case SetDisplayBrightnessCommand:
case SetDisplayCodeCommand:
case SetDisplayNameCommand:
// TODO: Error handling // TODO: Error handling
this->refreshLoadingState(); this->refreshLoadingState();
break; break;
}
case SetDisplayBrightnessCommand: {
// TODO: Error handling
this->refreshLoadingState();
break;
}
} }
} }
@ -233,8 +241,8 @@ void OmobiDisplayBackend::updateDisplayTextSetParameter(int index, int parameter
this->sendBluetoothCommand(SetTextSetParameterCommand, dataMap); this->sendBluetoothCommand(SetTextSetParameterCommand, dataMap);
} }
QBluetoothLeUart* OmobiDisplayBackend::getBleController() { QBluetoothLeUartClient* OmobiDisplayBackend::getBleClient() {
return this->ble; return this->bleClient;
} }
@ -270,7 +278,7 @@ void OmobiDisplayBackend::setState(OmobiDisplayAppState state) {
qDebug() << "Now in " << state << " state"; qDebug() << "Now in " << state << " state";
if(this->state == Idle) if(this->state == Idle)
this->ble->startScanningForDevices(); this->bleClient->startScanningForDevices();
} }
int OmobiDisplayBackend::getDisplayBrightness() { int OmobiDisplayBackend::getDisplayBrightness() {
@ -287,3 +295,13 @@ void OmobiDisplayBackend::setDisplayBrightness(int brightness) {
emit this->displayBrightnessChanged(); emit this->displayBrightnessChanged();
} }
void OmobiDisplayBackend::setDisplayCode(QString code) {
this->sendBluetoothCommand(SetDisplayCodeCommand, QVariantMap{{"displayCode",code}});
}
void OmobiDisplayBackend::setDisplayName(QString name) {
// This will restart the display!!
this->sendBluetoothCommand(SetDisplayNameCommand, QVariantMap{{"displayName", name}});
}

View file

@ -6,13 +6,13 @@
#include <QJsonDocument> #include <QJsonDocument>
#include <QCryptographicHash> #include <QCryptographicHash>
#include <qbluetoothleuart.h> #include <qbluetoothleuartclient.h>
#include <omobidisplaytextmodel.h> #include <omobidisplaytextmodel.h>
class OmobiDisplayBackend : public QObject class OmobiDisplayBackend : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QBluetoothLeUart* bleController READ getBleController NOTIFY bleControllerChanged) Q_PROPERTY(QBluetoothLeUartClient* bleClient READ getBleClient NOTIFY bleClientChanged)
Q_PROPERTY(OmobiDisplayAppState state READ getState WRITE setState NOTIFY stateChanged) Q_PROPERTY(OmobiDisplayAppState state READ getState WRITE setState NOTIFY stateChanged)
Q_PROPERTY(OmobiDisplayTextModel* displayTextModel READ getDisplayTextModel NOTIFY displayTextModelChanged) Q_PROPERTY(OmobiDisplayTextModel* displayTextModel READ getDisplayTextModel NOTIFY displayTextModelChanged)
Q_PROPERTY(int displayBrightness READ getDisplayBrightness WRITE setDisplayBrightness NOTIFY displayBrightnessChanged) Q_PROPERTY(int displayBrightness READ getDisplayBrightness WRITE setDisplayBrightness NOTIFY displayBrightnessChanged)
@ -25,6 +25,8 @@ public:
Scanning, Scanning,
ReadyToConnect, ReadyToConnect,
Connecting, Connecting,
AuthenticationRequired,
Authenticating,
Initing, Initing,
Connected, Connected,
Loading Loading
@ -39,7 +41,9 @@ private:
GetTextSetParameterCommand = 11, GetTextSetParameterCommand = 11,
GetDisplayBrightnessCommand = 12, GetDisplayBrightnessCommand = 12,
SetTextSetParameterCommand = 20, SetTextSetParameterCommand = 20,
SetDisplayBrightnessCommand = 21 SetDisplayBrightnessCommand = 21,
SetDisplayCodeCommand = 22,
SetDisplayNameCommand = 23
}; };
enum OmobiDisplayStatusCode { enum OmobiDisplayStatusCode {
@ -48,7 +52,7 @@ private:
}; };
OmobiDisplayAppState state; OmobiDisplayAppState state;
QBluetoothLeUart *ble; QBluetoothLeUartClient *bleClient;
QTimer *keepAliveTimer; QTimer *keepAliveTimer;
OmobiDisplayTextModel* displayTextModel; OmobiDisplayTextModel* displayTextModel;
int waitingCommands; int waitingCommands;
@ -57,14 +61,17 @@ private:
public slots: public slots:
Q_INVOKABLE void startScanning(); Q_INVOKABLE void startScanning();
Q_INVOKABLE QBluetoothLeUart* getBleController(); Q_INVOKABLE void authenticate(QString secret);
Q_INVOKABLE QBluetoothLeUartClient* getBleClient();
Q_INVOKABLE OmobiDisplayAppState getState(); Q_INVOKABLE OmobiDisplayAppState getState();
Q_INVOKABLE OmobiDisplayTextModel* getDisplayTextModel(); Q_INVOKABLE OmobiDisplayTextModel* getDisplayTextModel();
Q_INVOKABLE int getDisplayBrightness(); Q_INVOKABLE int getDisplayBrightness();
Q_INVOKABLE void setDisplayBrightness(int brightness); Q_INVOKABLE void setDisplayBrightness(int brightness);
Q_INVOKABLE void setDisplayCode(QString code);
Q_INVOKABLE void setDisplayName(QString name);
private slots: private slots:
void handleBluetoothStateChange(QBluetoothLeUart::BluetoothLeUartState state); void handleBluetoothStateChange(QBluetoothLeUartClient::BluetoothLeUartClientState state);
void handleFoundNewDevice(QBluetoothLeUartDevice* device); void handleFoundNewDevice(QBluetoothLeUartDevice* device);
void handleBluetoothDeviceConected(); void handleBluetoothDeviceConected();
@ -83,7 +90,7 @@ private slots:
signals: signals:
void stateChanged(); void stateChanged();
void bleControllerChanged(); void bleClientChanged();
void displayTextModelChanged(); void displayTextModelChanged();
void displayBrightnessChanged(); void displayBrightnessChanged();

View file

@ -1,6 +1,10 @@
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Controls 2.12 import QtQuick.Controls 2.12
import QtGraphicalEffects 1.12 import QtGraphicalEffects 1.12
import QtQuick.Templates 2.12 as T
import QtQuick.Controls.impl 2.12
import QtQuick.Controls.Material 2.12
import QtQuick.Controls.Material.impl 2.12
Item { Item {
id: control id: control
@ -10,11 +14,12 @@ Item {
property string text: "" property string text: ""
property string color: "" property string color: ""
property bool isDarkColor: control.checkIsDarkColor(color) property bool isDarkColor: control.checkIsDarkColor(color)
property double glowRadius: 0.001 property double glowRadius: 0.01
property double glowSpread: 0.2 property double glowSpread: 0.01
property bool glowVisible: true property bool glowVisible: true
property double glowScale: 0.9 property double glowScale: 1
property double glowOpacity: Math.pow( control.opacity, 100 ) property double glowOpacity: Math.pow( control.opacity, 100 ) * 0.5
property bool interactive: true
signal clicked signal clicked
@ -49,10 +54,42 @@ Item {
anchors.fill: parent anchors.fill: parent
color: control.color color: control.color
radius: height * 0.5 radius: height * 0.5
clip: true
Behavior on color { Behavior on color {
ColorAnimation {} ColorAnimation {}
} }
Ripple {
id: ripple
clipRadius: height
clip: true
width: parent.width
height: parent.height
pressed: mouseArea.pressed
anchor: background
active: mouseArea.pressed || mouseArea.visualFocus || mouseArea.containsMouse
color: control.Material.rippleColor
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Item {
width: ripple.width
height: ripple.height
Rectangle {
anchors.fill: parent
radius: Math.min(width, height) * 0.5
}
}
}
}
}
ColorOverlay {
source: ripple
color: "red"
} }
Text { Text {
@ -75,7 +112,7 @@ Item {
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
enabled: control.enabled enabled: control.enabled && control.interactive
onClicked: control.clicked() onClicked: control.clicked()
} }
} }

View file

@ -44,10 +44,11 @@ ItemDelegate {
} }
font.pixelSize: parent.height * 0.5 font.pixelSize: parent.height * 0.5
font.styleName: fontAwesome.name
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
text: ">" text: "\uf105"
} }
Dialog { Dialog {

View file

@ -42,12 +42,13 @@ ItemDelegate {
} }
font.pixelSize: parent.height * 0.5 font.pixelSize: parent.height * 0.5
font.styleName: fontAwesome.name
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
color: control.Material.foreground color: control.Material.foreground
text: ">" text: "\uf105"
} }
Dialog { Dialog {

View file

@ -4,38 +4,72 @@ import QtQuick.Layouts 1.0
import de.itsblue.omobidisplayapp 1.0 import de.itsblue.omobidisplayapp 1.0
import de.itsblue.bluetoothleuart 1.0 import de.itsblue.bluetoothleuart 1.0
import QtQuick.Controls.Material 2.0 import QtQuick.Controls.Material 2.0
import QtGraphicalEffects 1.0
Page { Page {
id: root id: root
property bool actionButtonVisible: false
property bool backButtonVisible: false
property string statusText property string statusText
property bool working property bool working
title: qsTr("Available displays")
ColumnLayout { ColumnLayout {
id: mainLayout
anchors { anchors {
fill: parent fill: parent
margins: parent.height * 0.01 margins: Math.min(parent.height, parent.width) * 0.05
topMargin: 0
} }
Text { Chip {
Layout.preferredWidth: parent.width * 0.6 Layout.fillWidth: true
Layout.preferredHeight: parent.height * 0.1 Layout.preferredHeight: mainLayout.height * 0.05
Layout.alignment: Layout.Center Layout.alignment: Layout.Center
color: "white"
verticalAlignment: Text.AlignVCenter onClicked: {
horizontalAlignment: Text.AlignHCenter backend.bleClient.startScanningForDevices()
}
fontSizeMode: Text.Fit RowLayout {
font.pixelSize: 500 spacing: mainLayout.anchors.margins
minimumPixelSize: 1
text: qsTr("Available devices") anchors.fill: parent
anchors.leftMargin: width * 0.05
anchors.rightMargin: 0
Text {
Layout.fillHeight: true
Layout.fillWidth: true
verticalAlignment: Text.AlignVCenter
font.pixelSize: parent.height * 0.4
text: root.statusText
}
BusyIndicator {
Layout.fillHeight: true
Layout.preferredWidth: height
id: busyIndicator
scale: 0.8
opacity: root.working ? 1:0
}
}
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: mainLayout.height * 0.025
} }
ListView { ListView {
id: availableDevicesListView id: availableDisplaysListView
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.fillHeight: true Layout.fillHeight: true
@ -44,7 +78,7 @@ Page {
clip: true clip: true
boundsBehavior: Flickable.OvershootBounds boundsBehavior: Flickable.OvershootBounds
model: backend.bleController.availableDevicesModel model: backend.bleClient.availableDevicesModel
add: Transition { add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200 } NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200 }
@ -58,64 +92,19 @@ Page {
spacing: 5 spacing: 5
header: ItemDelegate {
id: headerDelegate
width: parent.width
height: implicitHeight * 0.8
topInset: 10
bottomInset: 10
text: root.statusText
onClicked: backend.bleController.startScanningForDevices()
Rectangle {
anchors.fill: parent
anchors.topMargin: 10
anchors.bottomMargin: 10
color: "transparent"
border.color: "lightgrey"
border.width: 3
}
Item {
anchors {
right: parent.right
rightMargin: parent.height * 0.15
verticalCenter: parent.verticalCenter
}
height: (parent.height - 20) * 0.7
width: height
BusyIndicator {
id: busyIndicator
anchors.centerIn: parent
width: parent.width
height: parent.height
opacity: root.working ? 1:0
}
}
}
delegate: ItemDelegate { delegate: ItemDelegate {
width: parent.width width: parent.width
text: name text: name
onClicked: backend.bleController.connectToDevice(device) onClicked: backend.bleClient.connectToDevice(device)
Rectangle { Rectangle {
anchors { anchors {
top: parent.top top: parent.top
left: parent.left left: parent.left
right: parent.right right: parent.right
topMargin: - availableDevicesListView.spacing * 0.5 topMargin: - availableDisplaysListView.spacing * 0.5
} }
color: "lightgrey" color: "lightgrey"
@ -123,6 +112,100 @@ Page {
visible: index !== 0 visible: index !== 0
} }
} }
Item {
anchors.centerIn: parent
width: Math.min(parent.height, parent.width)
height: Math.min(parent.height, parent.width)
opacity: availableDisplaysListView.model.rowCount === 0 ? 1:0
Behavior on opacity {
NumberAnimation {}
}
Rectangle {
id: noDisplaysRect
anchors {
top: parent.top
topMargin: parent.height * 0.2
horizontalCenter: parent.horizontalCenter
}
width: parent.width * 0.7
height: width * 0.3
color: "transparent"
border.width: height * 0.15
border.color: "lightgrey"
Text {
anchors.centerIn: parent
anchors.verticalCenterOffset: text === "..." ? -height * 0.25:0
color: "lightgrey"
font.pixelSize: parent.height * 0.6
font.bold: true
text: parseInt(root.state) === OmobiDisplayBackend.Scanning ? "...":"?"
}
}
Text {
id: noDisplaysText
anchors {
top: noDisplaysRect.bottom
topMargin: noDisplaysRect.height * 0.15
horizontalCenter: parent.horizontalCenter
}
font.bold: true
font.pixelSize: noDisplaysRect.height * 0.3
color: Qt.darker("lightgrey", 1.1)
text: parseInt(root.state) === OmobiDisplayBackend.Scanning ? qsTr("Still scanning"):qsTr("No displays found")
}
}
}
}
Dialog {
id: authenticationDialog
property bool shouldBeOpened: false
parent: Overlay.overlay
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: parent.width * 0.9
modal: true
closePolicy: Popup.NoAutoClose
standardButtons: Dialog.Ok | Dialog.Cancel
title: qsTr("Input code")
onShouldBeOpenedChanged: {
if(shouldBeOpened)
open()
else
close()
}
onAccepted: {
backend.authenticate(secretTextInput.text)
}
onRejected: {
backend.bleClient.disconnectFromDevice()
}
contentItem: TextField {
id: secretTextInput
placeholderText: qsTr("code")
Keys.onReturnPressed: authenticationDialog.accept()
} }
} }
@ -132,7 +215,7 @@ Page {
PropertyChanges { PropertyChanges {
target: root target: root
statusText: "Tap here to scan" statusText: qsTr("Tap here to scan")
working: false working: false
} }
}, },
@ -141,7 +224,7 @@ Page {
PropertyChanges { PropertyChanges {
target: root target: root
statusText: "Scanning..." statusText: qsTr("Scanning...")
working: true working: true
} }
}, },
@ -150,21 +233,56 @@ Page {
PropertyChanges { PropertyChanges {
target: root target: root
statusText: availableDevicesListView.model.rowCount() > 0 ? "Please select a device or tap to scan again":"No devices found. Tap to scan again" statusText: availableDisplaysListView.model.rowCount > 0 ? qsTr("Please select a device or tap to scan again"):qsTr("No displays found. Tap to scan again")
working: false working: false
} }
}, },
State { State {
name: OmobiDisplayBackend.Connecting name: OmobiDisplayBackend.AuthenticationRequired
PropertyChanges { PropertyChanges {
target: availableDevicesListView target: authenticationDialog
shouldBeOpened: true
}
PropertyChanges {
target: availableDisplaysListView
enabled: false enabled: false
} }
PropertyChanges { PropertyChanges {
target: root target: root
statusText: "trying to connect..." statusText: qsTr("trying to authenticate...")
working: true
}
},
State {
name: OmobiDisplayBackend.Authenticating
PropertyChanges {
target: availableDisplaysListView
enabled: false
}
PropertyChanges {
target: root
statusText: qsTr("trying to authenticate...")
working: true
}
},
State {
name: OmobiDisplayBackend.Connecting
PropertyChanges {
target: availableDisplaysListView
enabled: false
}
PropertyChanges {
target: root
statusText: qsTr("trying to connect...")
working: true working: true
} }
}, },
@ -172,13 +290,13 @@ Page {
name: OmobiDisplayBackend.Initing name: OmobiDisplayBackend.Initing
PropertyChanges { PropertyChanges {
target: availableDevicesListView target: availableDisplaysListView
enabled: false enabled: false
} }
PropertyChanges { PropertyChanges {
target: root target: root
statusText: "loading data..." statusText: qsTr("loading data...")
working: true working: true
} }
} }

View file

@ -2,6 +2,7 @@ import QtQuick 2.0
import QtQuick.Controls 2.9 import QtQuick.Controls 2.9
import QtQuick.Layouts 1.0 import QtQuick.Layouts 1.0
import QtQuick.Controls.Material 2.0 import QtQuick.Controls.Material 2.0
import QtGraphicalEffects 1.0
import de.itsblue.omobidisplayapp 1.0 import de.itsblue.omobidisplayapp 1.0
import de.itsblue.bluetoothleuart 1.0 import de.itsblue.bluetoothleuart 1.0
@ -9,53 +10,79 @@ import de.itsblue.bluetoothleuart 1.0
Page { Page {
id: root id: root
property bool actionButtonVisible: true
property bool backButtonVisible: true
title: backend.bleClient.currentDevice === null ? "":backend.bleClient.currentDevice.name
function backButtonClicked() {
backend.bleClient.disconnectFromDevice()
}
function actionButtonClicked() {
displayEditDialog.edit()
}
ColumnLayout { ColumnLayout {
id: mainLayout
anchors { anchors {
fill: parent fill: parent
margins: parent.height * 0.01 margins: Math.min(parent.height, parent.width) * 0.05
topMargin: 0
} }
Text { Chip {
Layout.preferredWidth: parent.width * 0.6
Layout.preferredHeight: parent.height * 0.1
Layout.alignment: Layout.Center
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
fontSizeMode: Text.Fit
font.pixelSize: 500
minimumPixelSize: 1
color: root.Material.foreground
text: "Omobi Display 1" //backend.bleController.currentDevice.name
}
Text {
Layout.alignment: Layout.Center
color: root.Material.foreground
text: qsTr("Brightness:")
}
Slider {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: mainLayout.height * 0.05
Layout.alignment: Layout.Center
from: 0 interactive: false
to: 10
stepSize: 1
value: backend.displayBrightness color: "white"
onPressedChanged: { RowLayout {
if(!pressed) spacing: mainLayout.anchors.margins
backend.displayBrightness = value
anchors.fill: parent
anchors.leftMargin: width * 0.05
anchors.rightMargin: anchors.leftMargin
Text {
Layout.fillHeight: true
verticalAlignment: Text.AlignVCenter
font.pixelSize: parent.height * 0.5
text: "\uf186"
}
Slider {
Layout.fillWidth: true
Layout.fillHeight: true
from: 0
to: 10
stepSize: 1
value: backend.displayBrightness
onPressedChanged: {
if(!pressed)
backend.displayBrightness = value
}
}
Text {
Layout.fillHeight: true
verticalAlignment: Text.AlignVCenter
font.pixelSize: parent.height * 0.5
text: "\uf185"
}
} }
} }
Item {
Layout.fillWidth: true
Layout.preferredHeight: mainLayout.height * 0.025
}
DisplayTextModelListView { DisplayTextModelListView {
Layout.preferredWidth: parent.width Layout.preferredWidth: parent.width
Layout.fillHeight: true Layout.fillHeight: true
@ -65,6 +92,10 @@ Page {
} }
} }
DisplayEditDialog {
id: displayEditDialog
}
Dialog { Dialog {
id: loadingDialog id: loadingDialog

View file

@ -0,0 +1,91 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.9
import QtQuick.Controls.Material 2.0
import de.itsblue.omobidisplayapp 1.0
Dialog {
id: control
parent: Overlay.overlay
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: parent.width * 0.9
modal: true
title: qsTr("Edit display settings")
onAccepted: {
backend.setDisplayCode(codeTextField.value)
backend.setDisplayName(nameTextField.value)
}
contentItem: ColumnLayout {
id: dataFieldsGridLayout
width: control.width * 0.9
TextInputDelegate {
id: nameTextField
Layout.fillWidth: true
required: true
text: qsTr("Display name\n(needs restart)")
}
PasswordInputDelegate {
id: codeTextField
Layout.fillWidth: true
required: true
text: qsTr("Display code (4 digits)")
placeholderText: qsTr("Enter new display code")
repeatPlaceholderText: qsTr("Enter new display code again")
}
}
footer: DialogButtonBox {
// alignment: Qt.AlignHCenter
buttonLayout: DialogButtonBox.GnomeLayout
Material.background: "transparent"
Button {
flat: true
enabled: nameTextField.value !== ""
text: "save"
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
}
Button {
flat: true
text: "cancel"
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
}
}
function edit() {
reset()
nameTextField.value = backend.bleClient.currentDevice.name
open()
}
function add(model) {
editingModel = model
editing = false
reset()
open()
}
function reset() {
nameTextField.value = ""
codeTextField.value = ""
}
}

View file

@ -56,7 +56,7 @@ ItemDelegate {
ColorAnimation {} ColorAnimation {}
} }
text: model.scroll ? qsTr("scrolling"):qsTr("false") text: model.scroll ? qsTr("scrolling"):""
onClicked: { onClicked: {
control.clicked() control.clicked()

View file

@ -1,6 +0,0 @@
import QtQuick 2.0
import QtQuick.Controls 2.9
ItemDelegate {
}

View file

@ -0,0 +1,120 @@
import QtQuick 2.0
import QtQuick.Controls 2.9
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.0
ItemDelegate {
id: control
property string value: ""
property bool required: false
property color textColor: control.required && value === "" ? "red":control.Material.foreground
property string placeholderText: ""
property string repeatPlaceholderText: ""
property int minimumLength: 4
property int maximumLength: 4
onClicked: {
textField.text = value
textEditDialog.open()
}
Text {
anchors {
right: nextPageIconText.left
verticalCenter: parent.verticalCenter
rightMargin: control.padding
}
width: parent.width * 0.6
elide: Text.ElideRight
font.pixelSize: parent.font.pixelSize
horizontalAlignment: Text.AlignRight
text: "****"
}
Text {
id: nextPageIconText
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
rightMargin: control.padding
}
font.pixelSize: parent.height * 0.5
font.styleName: fontAwesome.name
verticalAlignment: Text.AlignVCenter
text: "\uf105"
}
Dialog {
id: textEditDialog
parent: Overlay.overlay
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: parent.width * 0.9
Material.theme: control.Material.theme
Material.accent: control.Material.accent
modal: true
title: control.text
contentItem: ColumnLayout {
TextField {
id: textField
Layout.fillWidth: true
placeholderText: control.placeholderText
text: control.value
color: text.length < 4 || text.length > 4 ? "red":control.Material.foreground
}
TextField {
id: repeatTextField
Layout.fillWidth: true
placeholderText: control.repeatPlaceholderText
text: control.value
color: repeatTextField.text !== textField.text ? "red":control.Material.foreground
}
}
footer: DialogButtonBox {
// alignment: Qt.AlignHCenter
buttonLayout: DialogButtonBox.GnomeLayout
Material.background: "transparent"
Button {
flat: true
enabled: !(textField.text.length < 4 || textField.text.length > 4) && textField.text === repeatTextField.text
text: "save"
DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
}
Button {
flat: true
text: "cancel"
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
}
}
onAccepted: {
control.value = textField.text
}
}
}

View file

@ -38,12 +38,13 @@ ItemDelegate {
} }
font.pixelSize: parent.height * 0.5 font.pixelSize: parent.height * 0.5
font.styleName: fontAwesome.name
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
color: control.Material.foreground color: control.Material.foreground
text: ">" text: "\uf105"
} }
Dialog { Dialog {

View file

@ -62,9 +62,6 @@ Dialog {
ColumnLayout { ColumnLayout {
id: dataFieldsGridLayout id: dataFieldsGridLayout
property double fontSizeMultiplier: 0.14
property double labelWidthMultiplier: 0.4
width: control.width * 0.9 width: control.width * 0.9
SwitchDelegate { SwitchDelegate {
@ -119,7 +116,7 @@ Dialog {
id: scrollCountSpinBox id: scrollCountSpinBox
Layout.fillWidth: true Layout.fillWidth: true
from: 0 from: 0
text: qsTr("Scroll count:") text: qsTr("Scroll count")
} }
} }
} }

View file

@ -22,7 +22,7 @@ ItemDelegate {
rightMargin: control.padding rightMargin: control.padding
} }
width: parent.width * 0.6 width: parent.width * 0.4
elide: Text.ElideRight elide: Text.ElideRight
font.pixelSize: parent.font.pixelSize font.pixelSize: parent.font.pixelSize
@ -43,12 +43,13 @@ ItemDelegate {
} }
font.pixelSize: parent.height * 0.5 font.pixelSize: parent.height * 0.5
font.styleName: fontAwesome.name
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
color: control.textColor color: control.textColor
text: ">" text: "\uf105"
} }
Dialog { Dialog {
@ -73,6 +74,8 @@ ItemDelegate {
placeholderText: control.placeholderText placeholderText: control.placeholderText
text: control.value text: control.value
Keys.onReturnPressed: textEditDialog.accept()
} }
onAccepted: { onAccepted: {

View file

@ -4,12 +4,13 @@ import QtQuick.Window 2.12
import de.itsblue.omobidisplayapp 1.0 import de.itsblue.omobidisplayapp 1.0
import de.itsblue.bluetoothleuart 1.0 import de.itsblue.bluetoothleuart 1.0
import QtQuick.Controls.Material 2.0 import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.0
ApplicationWindow { ApplicationWindow {
width: 540 width: 540
height: 960 height: 960
visible: true visible: true
title: qsTr("Hello World") title: qsTr("Itsblue smart display")
Page { Page {
id: app id: app
@ -26,22 +27,84 @@ ApplicationWindow {
Material.theme: Material.System Material.theme: Material.System
header: ToolBar { header: ToolBar {
id: headerToolBar
height: 50
implicitWidth: parent.width
Material.background: "white" Material.background: "white"
Image { RowLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: parent.height * 0.1
fillMode: Image.PreserveAspectFit ToolButton {
source: "qrc:/omobi.png" id: backToolButton
enabled: false
Layout.fillHeight: true
Layout.preferredWidth: height
opacity: mainStack.currentItem.backButtonVisible ? 1:0
font.styleName: fontAwesome.name
font.pixelSize: height * 0.6
Material.foreground: "black"
text: "\uf104"
contentItem: Item {}
Text {
anchors.centerIn: parent
font.pixelSize: parent.font.pixelSize
text: parent.text
}
onClicked: mainStack.currentItem.backButtonClicked()
}
Text {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.alignment: Layout.Center
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: mainStack.currentItem.title
}
ToolButton {
id: actionToolButton
Layout.fillHeight: true
Layout.preferredWidth: height
opacity: mainStack.currentItem.actionButtonVisible ? 1:0
font.styleName: fontAwesome.name
font.pixelSize: height * 0.4
Material.foreground: "black"
flat: true
text: "\uf013"
onClicked: mainStack.currentItem.actionButtonClicked()
}
} }
} }
OmobiDisplayBackend { OmobiDisplayBackend {
id: backend id: backend
} }
FontLoader {
id: fontAwesome
source: "qrc:/fa5regular.woff"
}
StackView { StackView {
id: mainStack id: mainStack
@ -56,6 +119,22 @@ ApplicationWindow {
initialItem: connectedPageComp initialItem: connectedPageComp
replaceEnter: Transition {
NumberAnimation {
properties: "opacity"
from: 0
to: 1
}
}
replaceExit: Transition {
NumberAnimation {
properties: "opacity"
from: 1
to: 0
}
}
Component { Component {
id: connectPageComp id: connectPageComp
ConnectPage { ConnectPage {
@ -66,6 +145,7 @@ ApplicationWindow {
Component { Component {
id: connectedPageComp id: connectedPageComp
ConnectedPage { ConnectedPage {
opacity: 0
state: app.state state: app.state
} }
} }
@ -104,6 +184,22 @@ ApplicationWindow {
} }
}, },
State {
name: OmobiDisplayBackend.AuthenticationRequired
PropertyChanges {
target: mainStack
currentComponent: connectPageComp
}
},
State {
name: OmobiDisplayBackend.Authenticating
PropertyChanges {
target: mainStack
currentComponent: connectPageComp
}
},
State { State {
name: OmobiDisplayBackend.Initing name: OmobiDisplayBackend.Initing
PropertyChanges { PropertyChanges {
@ -118,6 +214,14 @@ ApplicationWindow {
target: mainStack target: mainStack
currentComponent: connectedPageComp currentComponent: connectedPageComp
} }
PropertyChanges {
target: headerToolBar
state: "open"
}
PropertyChanges {
target: backToolButton
enabled: true
}
}, },
State { State {
@ -126,6 +230,14 @@ ApplicationWindow {
target: mainStack target: mainStack
currentComponent: connectedPageComp currentComponent: connectedPageComp
} }
PropertyChanges {
target: headerToolBar
state: "open"
}
PropertyChanges {
target: backToolButton
enabled: true
}
} }
] ]
} }

View file

@ -7,11 +7,12 @@
<file>DisplayTextModelListView.qml</file> <file>DisplayTextModelListView.qml</file>
<file>TextEditDialog.qml</file> <file>TextEditDialog.qml</file>
<file>TextInputDelegate.qml</file> <file>TextInputDelegate.qml</file>
<file>NextPageDelegate.qml</file>
<file>SpinBoxDelegate.qml</file> <file>SpinBoxDelegate.qml</file>
<file>ComboBoxDelegate.qml</file> <file>ComboBoxDelegate.qml</file>
<file>ColorPickerDelegate.qml</file> <file>ColorPickerDelegate.qml</file>
<file>ColorPicker.qml</file> <file>ColorPicker.qml</file>
<file>Chip.qml</file> <file>Chip.qml</file>
<file>DisplayEditDialog.qml</file>
<file>PasswordInputDelegate.qml</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

View file

@ -2,5 +2,6 @@
<qresource prefix="/"> <qresource prefix="/">
<file>omobi.png</file> <file>omobi.png</file>
<file>itsblue.png</file> <file>itsblue.png</file>
<file>fa5regular.woff</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

View file

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE" sourcelanguage="en">
<context>
<name>ConnectPage</name>
<message>
<source>Available devices</source>
<translation type="vanished">Verfügbare Geräte</translation>
</message>
<message>
<source>Input code</source>
<translation>Geben sie den Code ein</translation>
</message>
<message>
<source>code</source>
<translation>Code</translation>
</message>
<message>
<source>Tap here to scan</source>
<translation>Tippe hier um zu suchen</translation>
</message>
<message>
<source>Scanning...</source>
<translation>Suchen...</translation>
</message>
<message>
<source>Please select a device or tap to scan again</source>
<translation>Wähle ein Display, oder tippe um erneut zu suchen</translation>
</message>
<message>
<source>trying to authenticate...</source>
<translation>Versuche anzumelden...</translation>
</message>
<message>
<source>trying to connect...</source>
<translation>Versuche zu verbinden...</translation>
</message>
<message>
<source>loading data...</source>
<translation>Lade Daten...</translation>
</message>
<message>
<source>Available displays</source>
<translation>Verfügbare Displays</translation>
</message>
<message>
<source>Still scanning</source>
<translation>Suche läuft</translation>
</message>
<message>
<source>No displays found</source>
<translation>Keine Displays gefunden</translation>
</message>
<message>
<source>No displays found. Tap to scan again</source>
<translation>Keine Displays gefunden. Tippe um erneut zu suchen</translation>
</message>
</context>
<context>
<name>ConnectedPage</name>
<message>
<source>Brightness:</source>
<translation type="vanished">Helligkeit:</translation>
</message>
<message>
<source>loading...</source>
<translation>laden...</translation>
</message>
</context>
<context>
<name>DisplayEditDialog</name>
<message>
<source>Edit display settings</source>
<translation>Display Einstellungen bearbeiten</translation>
</message>
<message>
<source>Display name
(needs restart)</source>
<translation>Displayname\n(neutstart nötig)</translation>
</message>
<message>
<source>Display code (4 digits)</source>
<translation>Display Code (4 Zeichen)</translation>
</message>
<message>
<source>Enter new display code</source>
<translation>Geben sie den neuen Display Code ein</translation>
</message>
<message>
<source>Enter new display code again</source>
<translation>Geben sie den neuen Display Code erneut ein</translation>
</message>
</context>
<context>
<name>DisplayTextDelegate</name>
<message>
<source>scrolling</source>
<translation>scrollen</translation>
</message>
<message>
<source>false</source>
<translation type="vanished">nein</translation>
</message>
<message>
<source> active </source>
<translation> aktiv </translation>
</message>
<message>
<source>inactive</source>
<translation>inaktiv</translation>
</message>
</context>
<context>
<name>TextEditDialog</name>
<message>
<source>Active</source>
<translation>Aktiv</translation>
</message>
<message>
<source>Enter some text to be displayed</source>
<translation>Geben sie den anzuzeigenden Text ein</translation>
</message>
<message>
<source>Text</source>
<translation>Text</translation>
</message>
<message>
<source>Runtime (in s)</source>
<translation>Laufzeit (in s)</translation>
</message>
<message>
<source>Color</source>
<translation>Farbe</translation>
</message>
<message>
<source>Alignment</source>
<translation>Ausrichtung</translation>
</message>
<message>
<source>Scroll</source>
<translation>Scrollen</translation>
</message>
<message>
<source>Scroll speed</source>
<translation>Scrollgeschwindigkeit</translation>
</message>
<message>
<source>Scroll count:</source>
<translation type="vanished">Scrolldurchläufe</translation>
</message>
<message>
<source>Scroll count</source>
<translation>Scrolldurchläufe</translation>
</message>
</context>
<context>
<name>main</name>
<message>
<source>Itsblue smart display</source>
<translation>Itsblue smart display</translation>
</message>
</context>
</TS>

View file

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>de.qm</file>
</qresource>
</RCC>

View file

@ -62,6 +62,8 @@ public:
bool getDeviceConnected(); bool getDeviceConnected();
bool disconnectCurrentDevice(); bool disconnectCurrentDevice();
String getDeviceAddress();
protected: protected:
// callbacks for BLEServer // callbacks for BLEServer
void onConnect(BLEServer *pServer, esp_ble_gatts_cb_param_t *param) override; void onConnect(BLEServer *pServer, esp_ble_gatts_cb_param_t *param) override;

View file

@ -27,25 +27,22 @@ private:
template <typename T> template <typename T>
const T &writeToEeprom(int address, size_t size, const T &t) const T &writeToEeprom(int address, size_t size, const T &t)
{ {
Serial.println("Writing at: " + String(address) + " size: " + String(sizeof(T)));
if (sizeof(T) > size) { if (sizeof(T) > size) {
Serial.println("Error writing: Size should be: " + String(size)); Serial.println("[Error][EepromManager] writing: Size should be: " + String(size) + " but was: " + String(sizeof(T)));
return t; return t;
} }
const T &res = EEPROM.put(address, t); const T &res = EEPROM.put(address, t);
Serial.println("Eeprom commit returned: " + String(EEPROM.commit())); EEPROM.commit();
return res; return res;
} }
template <typename T> template <typename T>
T &readFromEeprom(int address, size_t size, T &t) T &readFromEeprom(int address, size_t size, T &t)
{ {
Serial.println("Reading at: " + String(address) + " size: " + String(sizeof(T)));
if (sizeof(T) > size) { if (sizeof(T) > size) {
Serial.println("Error reading: Size should be: " + String(size)); Serial.println("[Error][EepromManager] reading: Size should be: " + String(size) + " but was: " + String(sizeof(T)));
return t; return t;
} }

View file

@ -54,12 +54,15 @@ private:
GetTextSetParameterCommand = 11, GetTextSetParameterCommand = 11,
GetDisplayBrightnessCommand = 12, GetDisplayBrightnessCommand = 12,
SetTextSetParameterCommand = 20, SetTextSetParameterCommand = 20,
SetDisplayBrightnessCommand = 21 SetDisplayBrightnessCommand = 21,
SetDisplayCodeCommand = 22,
SetDisplayNameCommand = 23
}; };
enum OmobiDisplayStatusCode enum OmobiDisplayStatusCode
{ {
Success = 200, Success = 200,
BadRequestError = 400,
Unauthorized = 401, Unauthorized = 401,
InternalError = 500, InternalError = 500,
DisplayControllerError = 501 DisplayControllerError = 501

View file

@ -56,6 +56,27 @@ void BluetoothLeUartServer::sendData(String data)
txCharacteristic->notify(); txCharacteristic->notify();
} }
bool BluetoothLeUartServer::getDeviceConnected()
{
return this->deviceConnected;
}
bool BluetoothLeUartServer::disconnectCurrentDevice() {
if(!this->getDeviceConnected())
return false;
this->bleServer->disconnect(this->deviceConnectionId);
return true;
}
String BluetoothLeUartServer::getDeviceAddress() {
String address = BLEDevice::getAddress().toString().c_str();
address.toUpperCase();
return address;
}
void BluetoothLeUartServer::onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param) void BluetoothLeUartServer::onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param)
{ {
// only allow one device // only allow one device
@ -85,16 +106,3 @@ void BluetoothLeUartServer::onWrite(BLECharacteristic *rxCharacteristic)
if (this->callbacks != nullptr) if (this->callbacks != nullptr)
this->callbacks->onDataReceived(rxCharacteristic->getValue().c_str()); this->callbacks->onDataReceived(rxCharacteristic->getValue().c_str());
} }
bool BluetoothLeUartServer::getDeviceConnected()
{
return this->deviceConnected;
}
bool BluetoothLeUartServer::disconnectCurrentDevice() {
if(!this->getDeviceConnected())
return false;
this->bleServer->disconnect(this->deviceConnectionId);
return true;
}

View file

@ -8,7 +8,6 @@ EepromManager::EepromManager()
EepromUnit *EepromManager::registerEempromUnit(size_t size) EepromUnit *EepromManager::registerEempromUnit(size_t size)
{ {
Serial.println("Registering new EepromUnit with size: " + String(size) + " at " + String(this->currentAddressEnding));
// create a new Unit at the current address ending // create a new Unit at the current address ending
EepromUnit *newUnit = new EepromUnit(this, this->currentAddressEnding, size); EepromUnit *newUnit = new EepromUnit(this, this->currentAddressEnding, size);
// move the new address ending // move the new address ending

View file

@ -48,18 +48,21 @@ void OmobiLedDisplay::onDataReceived(String dataString)
OmobiDisplayStatusCode replyStatus = InternalError; OmobiDisplayStatusCode replyStatus = InternalError;
JsonObject replyData = replyDoc.createNestedObject("data"); JsonObject replyData = replyDoc.createNestedObject("data");
if (requestHeader != AuthorizeSessionCommand && !this->sessionAuthorized) if (requestHeader > KeepAliveCommand && !this->sessionAuthorized)
replyStatus = Unauthorized; replyStatus = Unauthorized;
else else
switch (requestHeader) switch (requestHeader)
{ {
case AuthorizeSessionCommand: case AuthorizeSessionCommand:
{ {
String combinedCode = this->bleServer->getDeviceAddress() + String(this->properties.deviceCode);
String secret = this->sha256(combinedCode);
if (this->sessionAuthorized) if (this->sessionAuthorized)
{ {
replyStatus = Success; replyStatus = Success;
} }
else if (requestData["secret"] == this->sha256(this->properties.deviceCode)) else if (requestData["secret"] == secret)
{ {
replyStatus = Success; replyStatus = Success;
this->sessionAuthorized = true; this->sessionAuthorized = true;
@ -150,6 +153,30 @@ void OmobiLedDisplay::onDataReceived(String dataString)
replyStatus = Success; replyStatus = Success;
break; break;
} }
case SetDisplayCodeCommand: {
String code = requestData["displayCode"];
if(code.length() != 4) {
replyStatus = BadRequestError;
break;
}
strncpy(this->properties.deviceCode, code.c_str(), sizeof(this->properties.deviceCode));
this->storeProperties();
replyStatus = Success;
break;
}
case SetDisplayNameCommand: {
String name = requestData["displayName"];
if(name.length() <= 0) {
replyStatus = BadRequestError;
break;
}
strncpy(this->properties.deviceName, name.c_str(), sizeof(this->properties.deviceName));
this->storeProperties();
replyStatus = Success;
break;
}
default: default:
break; break;
} }