LedDisplay/OmobiDisplayApp/omobidisplaybackend.cpp

308 lines
10 KiB
C++
Raw Normal View History

2020-10-15 16:57:07 +02:00
#include "omobidisplaybackend.h"
2020-10-08 20:06:57 +02:00
OmobiDisplayBackend::OmobiDisplayBackend(QObject *parent) : QObject(parent)
{
this->bleClient = new QBluetoothLeUartClient();
this->bleClient->setUUIDs("92fecb20-1406-426a-afa5-cd5c1f306462", "92fecb21-1406-426a-afa5-cd5c1f306462", "92fecb22-1406-426a-afa5-cd5c1f306462");
2020-10-11 21:01:21 +02:00
this->displayTextModel = new OmobiDisplayTextModel(this);
this->textSetsBuffer.clear();
this->displayBrightness = -1;
this->waitingCommands = 0;
2020-10-08 20:06:57 +02:00
2020-10-15 16:57:07 +02:00
this->keepAliveTimer = new QTimer(this);
this->keepAliveTimer->setInterval(5000);
this->keepAliveTimer->setSingleShot(false);
connect(this->keepAliveTimer, &QTimer::timeout, this, &OmobiDisplayBackend::sendBluetoothKeepAlive);
connect(this->bleClient, &QBluetoothLeUartClient::stateChanged, this, &OmobiDisplayBackend::handleBluetoothStateChange);
connect(this->bleClient, &QBluetoothLeUartClient::foundNewDevice, this, &OmobiDisplayBackend::handleFoundNewDevice);
connect(this->bleClient, &QBluetoothLeUartClient::dataReceived, this, &OmobiDisplayBackend::handleBluetoothDataReceived);
connect(this->bleClient, &QBluetoothLeUartClient::connectedToDevice, this, &OmobiDisplayBackend::handleBluetoothDeviceConected);
2020-10-11 21:01:21 +02:00
connect(this->displayTextModel, &OmobiDisplayTextModel::dataChanged, this, &OmobiDisplayBackend::handleDisplayTextModelDataChanged);
connect(this->displayTextModel, &OmobiDisplayTextModel::rowsInserted, this, &OmobiDisplayBackend::handleDisplayTextModelRowsInserted);
connect(this->displayTextModel, &OmobiDisplayTextModel::rowsRemoved, this, &OmobiDisplayBackend::handleDisplayTextModelRowsRemoved);
2020-10-11 15:50:13 +02:00
this->setState(Idle);
this->bleClient->startScanningForDevices();
2020-10-08 20:06:57 +02:00
}
void OmobiDisplayBackend::startScanning() {
this->bleClient->startScanningForDevices();
2020-10-08 20:06:57 +02:00
}
2020-10-17 01:08:23 +02:00
void OmobiDisplayBackend::authenticate(QString code) {
// tell display to send over existing model data
this->setState(Authenticating);
QString combinedCode = this->bleClient->getCurrentDevice()->getAddress().toUpper() + code;
2020-10-17 01:08:23 +02:00
QString secret = QCryptographicHash::hash(combinedCode.toUtf8(), QCryptographicHash::Sha256).toHex();
this->sendBluetoothCommand(AuthorizeSessionCommand, QVariantMap{{"secret", secret}});
}
void OmobiDisplayBackend::handleBluetoothStateChange(QBluetoothLeUartClient::BluetoothLeUartClientState state){
2020-10-08 20:06:57 +02:00
switch(state){
case QBluetoothLeUartClient::Idle: {
2020-10-11 15:50:13 +02:00
this->setState(Idle);
break;
}
case QBluetoothLeUartClient::Scanning: {
2020-10-11 15:50:13 +02:00
this->setState(Scanning);
break;
}
case QBluetoothLeUartClient::ScanFinished: {
2020-10-11 15:50:13 +02:00
this->setState(ReadyToConnect);
break;
}
case QBluetoothLeUartClient::Connecting: {
2020-10-11 15:50:13 +02:00
this->setState(Connecting);
break;
}
case QBluetoothLeUartClient::ScanningForService: {
2020-10-11 15:50:13 +02:00
this->setState(Connecting);
break;
}
case QBluetoothLeUartClient::ServiceFound: {
2020-10-11 15:50:13 +02:00
this->setState(Connecting);
break;
}
case QBluetoothLeUartClient::Connected:
2020-10-11 15:50:13 +02:00
{
2020-10-08 20:06:57 +02:00
break;
2020-10-11 15:50:13 +02:00
}
2020-10-08 20:06:57 +02:00
}
2020-10-15 16:57:07 +02:00
if(state == QBluetoothLeUartClient::Connected)
2020-10-15 16:57:07 +02:00
this->keepAliveTimer->start();
else if(this->keepAliveTimer->isActive())
this->keepAliveTimer->stop();
2020-10-08 20:06:57 +02:00
}
2020-10-09 00:03:50 +02:00
void OmobiDisplayBackend::handleBluetoothDeviceConected() {
2020-10-17 01:08:23 +02:00
this->setState(AuthenticationRequired);
this->authenticate("1234");
2020-10-17 01:08:23 +02:00
// TODO: stuff
2020-10-09 00:03:50 +02:00
}
2020-10-08 22:03:30 +02:00
void OmobiDisplayBackend::handleFoundNewDevice(QBluetoothLeUartDevice* device) {
2020-10-08 20:06:57 +02:00
qDebug() << "Found a device: name: " << device->getName() << " address: " << device->getAddress();
}
void OmobiDisplayBackend::handleDisplayTextModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) {
2020-10-15 16:57:07 +02:00
qDebug() << "Data changed: topLeft: " << topLeft << " bottomRight: " << bottomRight << " roles: " << roles;
2020-10-15 16:57:07 +02:00
for(int role : roles)
this->updateDisplayTextSetParameter(topLeft.row(), role);
}
void OmobiDisplayBackend::handleDisplayTextModelRowsInserted(const QModelIndex &parent, int first, int last) {
qDebug() << "Rows inserted: parent: " << parent << " first: " << first << " last " << last;
for(int i = 0; i < OmobiDisplayTextModel::OmobiDisplayTextModelRoleCount; i++) {
this->updateDisplayTextSetParameter(first, i);
}
}
void OmobiDisplayBackend::handleDisplayTextModelRowsRemoved(const QModelIndex &parent, int first, int last) {
qDebug() << "Rows removed: parent: " << parent << " first: " << first << " last " << last;
// Setting Text to "" will delete the item
this->updateDisplayTextSetParameter(first, OmobiDisplayTextModel::TextRole, "");
}
void OmobiDisplayBackend::sendBluetoothCommand(OmobiDisplayCommand command, QVariant data) {
QVariantMap commandMap = {
{"header", command},
{"data", data}
};
QJsonDocument doc = QJsonDocument::fromVariant(commandMap);
qDebug() << "Sending command: \n" << qPrintable(doc.toJson(QJsonDocument::Indented));
this->waitingCommands ++;
if(this->state == Connected)
this->setState(Loading);
this->bleClient->sendData(doc.toJson(QJsonDocument::Compact));
2020-10-08 20:06:57 +02:00
}
2020-10-15 16:57:07 +02:00
void OmobiDisplayBackend::sendBluetoothKeepAlive() {
QJsonDocument doc = QJsonDocument::fromVariant(QVariantMap{{"header", KeepAliveCommand}});
qDebug() << "Sending keep alive: \n" << qPrintable(doc.toJson(QJsonDocument::Indented));
this->bleClient->sendData(doc.toJson(QJsonDocument::Compact));
2020-10-15 16:57:07 +02:00
}
void OmobiDisplayBackend::handleBluetoothDataReceived(QString s){
qDebug() << "New data: \n" << qPrintable(s);
2020-10-11 21:01:21 +02:00
QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(s.toUtf8(), &parseError);
if(parseError.error != QJsonParseError::NoError)
return;
OmobiDisplayCommand header = OmobiDisplayCommand(doc.toVariant().toMap()["header"].toInt());
QVariantMap data = doc.toVariant().toMap()["data"].toMap();
OmobiDisplayStatusCode status = OmobiDisplayStatusCode(doc.toVariant().toMap()["status"].toInt());
switch (header) {
2020-10-15 16:57:07 +02:00
case AuthorizeSessionCommand: {
2020-10-17 01:08:23 +02:00
if(status != Success) {
this->setState(AuthenticationRequired);
return;
}
this->waitingCommands = 0;
this->setState(Initing);
this->sendBluetoothCommand(GetAllTextSetsCommand);
this->sendBluetoothCommand(GetDisplayBrightnessCommand);
2020-10-15 16:57:07 +02:00
break;
}
case KeepAliveCommand: {
break;
}
case GetAllTextSetsCommand: {
// indicates that all existing txt sets have been sent over after GetAllTextSetsCommand was called
if(status != Success)
// TODO: handle error
break;
this->displayTextModel->maximumTextLength = data["maximumTextLength"].toInt();
this->displayTextModel->maximumTextSets = data["maximumTextSets"].toInt();
this->displayTextModel->setTexts(this->textSetsBuffer);
this->textSetsBuffer.clear();
this->refreshLoadingState();
break;
}
case GetTextSetParameterCommand: {
int index = data["index"].toInt();
if(index < 0)
return;
while(this->textSetsBuffer.length() <= index)
this->textSetsBuffer.append(QMap<int, QVariant>());
int parameter = data["parameter"].toInt();
if(!this->textSetsBuffer[index].contains(parameter))
this->textSetsBuffer[index].insert(parameter, QVariant());
2020-10-13 17:00:25 +02:00
this->textSetsBuffer[index][parameter] = data["value"].toString();
if(this->state != Initing)
this->refreshLoadingState();
break;
}
case GetDisplayBrightnessCommand: {
this->setDisplayBrightness(data["displayBrightness"].toInt());
this->refreshLoadingState();
break;
}
2020-10-17 03:22:37 +02:00
case SetTextSetParameterCommand:
case SetDisplayBrightnessCommand:
case SetDisplayCodeCommand:
case SetDisplayNameCommand:
// TODO: Error handling
this->refreshLoadingState();
break;
2020-10-17 03:22:37 +02:00
}
}
void OmobiDisplayBackend::updateDisplayTextSetParameter(int index, int parameter) {
this->updateDisplayTextSetParameter(index, parameter, this->displayTextModel->data(index, parameter).toString());
}
void OmobiDisplayBackend::updateDisplayTextSetParameter(int index, int parameter, QString value) {
if(this->state == Initing)
return;
qDebug() << "Updating data at index: " << index << " parameter: " << parameter << " and value: " << value;
QVariantMap dataMap = {
{"index", index},
{"parameter", parameter},
{"value", value}
};
this->sendBluetoothCommand(SetTextSetParameterCommand, dataMap);
2020-10-11 21:01:21 +02:00
}
QBluetoothLeUartClient* OmobiDisplayBackend::getBleClient() {
return this->bleClient;
2020-10-09 00:03:50 +02:00
}
2020-10-11 15:50:13 +02:00
2020-10-11 21:01:21 +02:00
OmobiDisplayTextModel* OmobiDisplayBackend::getDisplayTextModel() {
return this->displayTextModel;
}
2020-10-11 15:50:13 +02:00
OmobiDisplayBackend::OmobiDisplayAppState OmobiDisplayBackend::getState() {
return this->state;
}
void OmobiDisplayBackend::refreshLoadingState() {
if(this->state != Initing && this->state != Loading)
return;
qDebug() << "Refreshing loading state! Waiting: " << this->waitingCommands;
if(this->waitingCommands <= 1) {
this->waitingCommands = 0;
this->setState(Connected);
}
else
this->waitingCommands--;
}
2020-10-11 15:50:13 +02:00
void OmobiDisplayBackend::setState(OmobiDisplayAppState state) {
if(state == this->state)
return;
this->state = state;
emit this->stateChanged();
qDebug() << "Now in " << state << " state";
2020-10-11 15:50:13 +02:00
if(this->state == Idle)
this->bleClient->startScanningForDevices();
2020-10-11 15:50:13 +02:00
}
int OmobiDisplayBackend::getDisplayBrightness() {
return this->displayBrightness;
}
void OmobiDisplayBackend::setDisplayBrightness(int brightness) {
if(brightness == this->displayBrightness)
return;
this->displayBrightness = brightness;
this->sendBluetoothCommand(SetDisplayBrightnessCommand, QVariantMap{{"displayBrightness",this->displayBrightness}});
emit this->displayBrightnessChanged();
}
2020-10-17 03:22:37 +02:00
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}});
}