app now shows lots of new values and has a nice grid layout
This commit is contained in:
@@ -5,18 +5,32 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const QBluetoothUuid bobbycarServiceUuid{QUuid::fromString(QStringLiteral("0335e46c-f355-4ce6-8076-017de08cee98"))};
|
const QBluetoothUuid bobbycarServiceUuid{QUuid::fromString(QStringLiteral("0335e46c-f355-4ce6-8076-017de08cee98"))};
|
||||||
const QBluetoothUuid frontLeftSpeedCharacUuid{QUuid::fromString(QStringLiteral("81287506-8985-4cea-9a58-92fc5ad2c570"))};
|
|
||||||
const QBluetoothUuid frontRightSpeedCharacUuid{QUuid::fromString(QStringLiteral("2f326a23-a676-4f87-b5cb-37a8fd7fe466"))};
|
const QBluetoothUuid frontVoltageCharacUuid{QUuid::fromString(QStringLiteral("a48321ea-329f-4eab-a401-30e247211524"))};
|
||||||
const QBluetoothUuid backLeftSpeedCharacUuid{QUuid::fromString(QStringLiteral("a7f951c0-e984-460d-98ed-0d54c64092d5"))};
|
const QBluetoothUuid backVoltageCharacUuid{QUuid::fromString(QStringLiteral("4201def0-a264-43e6-946b-6b2d9612dfed"))};
|
||||||
const QBluetoothUuid backRightSpeedCharacUuid{QUuid::fromString(QStringLiteral("14efe73f-6e34-49b3-b2c7-b513f3f5aee2"))};
|
|
||||||
|
const QBluetoothUuid frontTemperatureCharacUuid{QUuid::fromString(QStringLiteral("4799e23f-6448-4786-900b-b5c3f3c17a9c"))};
|
||||||
|
const QBluetoothUuid backTemperatureCharacUuid{QUuid::fromString(QStringLiteral("3c32b7bb-8d9b-4055-8ea0-5b6764111024"))};
|
||||||
|
|
||||||
|
const QBluetoothUuid frontLeftErrorCharacUuid{QUuid::fromString(QStringLiteral("f84b3a9b-1b2c-4075-acbe-016a2166976c"))};
|
||||||
|
const QBluetoothUuid frontRightErrorCharacUuid{QUuid::fromString(QStringLiteral("eed4b709-5a65-4a5b-8e07-512f9661533d"))};
|
||||||
|
const QBluetoothUuid backLeftErrorCharacUuid{QUuid::fromString(QStringLiteral("89d143f5-9ae2-4f7e-9235-643a3a7e21df"))};
|
||||||
|
const QBluetoothUuid backRightErrorCharacUuid{QUuid::fromString(QStringLiteral("0fb377f1-7527-4966-aaf0-8bd56f2ddd3f"))};
|
||||||
|
|
||||||
|
const QBluetoothUuid frontLeftSpeedCharacUuid{QUuid::fromString(QStringLiteral("c6f959e8-0ec3-4bdd-88ad-6ad993fc81e9"))};
|
||||||
|
const QBluetoothUuid frontRightSpeedCharacUuid{QUuid::fromString(QStringLiteral("ce53f135-8f20-4b80-abb9-31da81d62716"))};
|
||||||
|
const QBluetoothUuid backLeftSpeedCharacUuid{QUuid::fromString(QStringLiteral("9a1dd1fe-3f14-4af1-bc5e-3f70edcae54b"))};
|
||||||
|
const QBluetoothUuid backRightSpeedCharacUuid{QUuid::fromString(QStringLiteral("7de1a823-682e-438f-9201-3a80c3911f1a"))};
|
||||||
|
|
||||||
|
const QBluetoothUuid frontLeftDcLinkCharacUuid{QUuid::fromString(QStringLiteral("f404416f-2a77-41c6-a35f-7d10ec38376d"))};
|
||||||
|
const QBluetoothUuid frontRightDcLinkCharacUuid{QUuid::fromString(QStringLiteral("452dd012-3f12-428c-8746-40c6b6c73c40"))};
|
||||||
|
const QBluetoothUuid backLeftDcLinkCharacUuid{QUuid::fromString(QStringLiteral("9dc455a3-718e-4d62-b0e7-1c0cb2a8bbd3"))};
|
||||||
|
const QBluetoothUuid backRightDcLinkCharacUuid{QUuid::fromString(QStringLiteral("90a66506-1d78-4ba2-b074-e1153fbf5216"))};
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceHandler::DeviceHandler(QObject *parent) :
|
DeviceHandler::DeviceHandler(QObject *parent) :
|
||||||
BluetoothBaseClass(parent),
|
BluetoothBaseClass(parent),
|
||||||
m_foundBobbycarService(false),
|
m_foundBobbycarService(false)
|
||||||
m_measuring(false),
|
|
||||||
m_currentValue(0),
|
|
||||||
m_min(0), m_max(0), m_sum(0), m_avg(0), m_distance(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,27 +99,6 @@ void DeviceHandler::setDevice(DeviceInfo *device)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandler::startMeasurement()
|
|
||||||
{
|
|
||||||
if (alive()) {
|
|
||||||
m_start = QDateTime::currentDateTime();
|
|
||||||
m_min = 0;
|
|
||||||
m_max = 0;
|
|
||||||
m_avg = 0;
|
|
||||||
m_sum = 0;
|
|
||||||
m_distance = 0;
|
|
||||||
m_measuring = true;
|
|
||||||
m_measurements.clear();
|
|
||||||
emit measuringChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceHandler::stopMeasurement()
|
|
||||||
{
|
|
||||||
m_measuring = false;
|
|
||||||
emit measuringChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceHandler::serviceDiscovered(const QBluetoothUuid &gatt)
|
void DeviceHandler::serviceDiscovered(const QBluetoothUuid &gatt)
|
||||||
{
|
{
|
||||||
if (gatt == bobbycarServiceUuid) {
|
if (gatt == bobbycarServiceUuid) {
|
||||||
@@ -138,6 +131,48 @@ void DeviceHandler::serviceScanDone()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void logAddr(const QBluetoothUuid &uuid)
|
||||||
|
{
|
||||||
|
if (uuid == bobbycarServiceUuid)
|
||||||
|
qDebug() << "bobbycarServiceUuid";
|
||||||
|
else if (uuid == frontVoltageCharacUuid)
|
||||||
|
qDebug() << "frontVoltageCharacUuid";
|
||||||
|
else if (uuid == backVoltageCharacUuid)
|
||||||
|
qDebug() << "backVoltageCharacUuid";
|
||||||
|
else if (uuid == frontTemperatureCharacUuid)
|
||||||
|
qDebug() << "frontTemperatureCharacUuid";
|
||||||
|
else if (uuid == backTemperatureCharacUuid)
|
||||||
|
qDebug() << "backTemperatureCharacUuid";
|
||||||
|
else if (uuid == frontLeftErrorCharacUuid)
|
||||||
|
qDebug() << "frontLeftErrorCharacUuid";
|
||||||
|
else if (uuid == frontRightErrorCharacUuid)
|
||||||
|
qDebug() << "frontRightErrorCharacUuid";
|
||||||
|
else if (uuid == backLeftErrorCharacUuid)
|
||||||
|
qDebug() << "backLeftErrorCharacUuid";
|
||||||
|
else if (uuid == backRightErrorCharacUuid)
|
||||||
|
qDebug() << "backRightErrorCharacUuid";
|
||||||
|
else if (uuid == frontLeftSpeedCharacUuid)
|
||||||
|
qDebug() << "frontLeftSpeedCharacUuid";
|
||||||
|
else if (uuid == frontRightSpeedCharacUuid)
|
||||||
|
qDebug() << "frontRightSpeedCharacUuid";
|
||||||
|
else if (uuid == backLeftSpeedCharacUuid)
|
||||||
|
qDebug() << "backLeftSpeedCharacUuid";
|
||||||
|
else if (uuid == backRightSpeedCharacUuid)
|
||||||
|
qDebug() << "backRightSpeedCharacUuid";
|
||||||
|
else if (uuid == frontLeftDcLinkCharacUuid)
|
||||||
|
qDebug() << "frontLeftDcLinkCharacUuid";
|
||||||
|
else if (uuid == frontRightDcLinkCharacUuid)
|
||||||
|
qDebug() << "frontRightDcLinkCharacUuid";
|
||||||
|
else if (uuid == backLeftDcLinkCharacUuid)
|
||||||
|
qDebug() << "backLeftDcLinkCharacUuid";
|
||||||
|
else if (uuid == backRightDcLinkCharacUuid)
|
||||||
|
qDebug() << "backRightDcLinkCharacUuid";
|
||||||
|
else
|
||||||
|
qDebug() << "unknown uuid" << uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DeviceHandler::serviceStateChanged(QLowEnergyService::ServiceState s)
|
void DeviceHandler::serviceStateChanged(QLowEnergyService::ServiceState s)
|
||||||
{
|
{
|
||||||
switch (s) {
|
switch (s) {
|
||||||
@@ -148,15 +183,197 @@ void DeviceHandler::serviceStateChanged(QLowEnergyService::ServiceState s)
|
|||||||
{
|
{
|
||||||
setInfo(tr("Service discovered."));
|
setInfo(tr("Service discovered."));
|
||||||
|
|
||||||
const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontLeftSpeedCharacUuid);
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontVoltageCharacUuid); hrChar.isValid())
|
||||||
if (!hrChar.isValid()) {
|
{
|
||||||
setError("Bobbycar Data not found.");
|
m_notificationDescFrontVoltage = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescFrontVoltage.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontVoltage, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("frontVoltageCharacUuid not found.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_notificationDesc = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(backVoltageCharacUuid); hrChar.isValid())
|
||||||
if (m_notificationDesc.isValid())
|
{
|
||||||
m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0100"));
|
m_notificationDescBackVoltage = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescBackVoltage.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackVoltage, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("backVoltageCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontTemperatureCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescFrontTemperature = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescFrontTemperature.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontTemperature, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("frontTemperatureCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(backTemperatureCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescBackTemperature = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescBackTemperature.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackTemperature, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("backTemperatureCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontLeftErrorCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescFrontLeftError = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescFrontLeftError.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontLeftError, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("frontLeftErrorCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontRightErrorCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescFrontRightError = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescFrontRightError.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontRightError, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("frontRightErrorCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(backLeftErrorCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescBackLeftError = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescBackLeftError.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackLeftError, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("backLeftErrorCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(backRightErrorCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescBackRightError = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescBackRightError.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackRightError, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("backRightErrorCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontLeftSpeedCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescFrontLeftSpeed = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescFrontLeftSpeed.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontLeftSpeed, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("frontLeftSpeedCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontRightSpeedCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescFrontRightSpeed = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescFrontRightSpeed.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontRightSpeed, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("frontRightSpeedCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(backLeftSpeedCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescBackLeftSpeed = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescBackLeftSpeed.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackLeftSpeed, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("backLeftSpeedCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(backRightSpeedCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescBackRightSpeed = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescBackRightSpeed.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackRightSpeed, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("backRightSpeedCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontLeftDcLinkCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescFrontLeftDcLink = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescFrontLeftDcLink.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontLeftDcLink, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("frontLeftDcLinkCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(frontRightDcLinkCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescFrontRightDcLink = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescFrontRightDcLink.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontRightDcLink, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("frontRightDcLinkCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(backLeftDcLinkCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescBackLeftDcLink = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescBackLeftDcLink.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackLeftDcLink, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("backLeftDcLinkCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const QLowEnergyCharacteristic hrChar = m_service->characteristic(backRightDcLinkCharacUuid); hrChar.isValid())
|
||||||
|
{
|
||||||
|
m_notificationDescBackRightDcLink = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||||
|
if (m_notificationDescBackRightDcLink.isValid())
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackRightDcLink, QByteArray::fromHex("0100"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("backRightDcLinkCharacUuid not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -170,25 +387,242 @@ void DeviceHandler::serviceStateChanged(QLowEnergyService::ServiceState s)
|
|||||||
|
|
||||||
void DeviceHandler::updateBobbycarValue(const QLowEnergyCharacteristic &c, const QByteArray &value)
|
void DeviceHandler::updateBobbycarValue(const QLowEnergyCharacteristic &c, const QByteArray &value)
|
||||||
{
|
{
|
||||||
// ignore any other characteristic change -> shouldn't really happen though
|
//qDebug() << "updateBobbycarValue";
|
||||||
if (c.uuid() != frontLeftSpeedCharacUuid)
|
//logAddr(c.uuid());
|
||||||
return;
|
|
||||||
|
|
||||||
bool ok;
|
if (c.uuid() == frontVoltageCharacUuid)
|
||||||
float val = value.toFloat(&ok);
|
{
|
||||||
if (ok)
|
bool ok;
|
||||||
addMeasurement(val);
|
float val = value.toFloat(&ok);
|
||||||
else
|
if (ok)
|
||||||
qWarning() << "could not parse float" << value;
|
{
|
||||||
|
m_frontVoltage = val;
|
||||||
|
emit frontVoltageChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse frontVoltage" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == backVoltageCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_backVoltage = val;
|
||||||
|
emit backVoltageChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse backVoltage" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == frontTemperatureCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_frontTemperature = val;
|
||||||
|
emit frontTemperatureChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse frontTemperature" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == backTemperatureCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_backTemperature = val;
|
||||||
|
emit backTemperatureChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse backTemperature" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == frontLeftErrorCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
uint8_t val = value.toShort(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_frontLeftError = val;
|
||||||
|
emit frontLeftErrorChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse frontLeftError" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == frontRightErrorCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
uint8_t val = value.toShort(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_frontRightError = val;
|
||||||
|
emit frontRightErrorChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse frontRightError" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == backLeftErrorCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
uint8_t val = value.toShort(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_backLeftError = val;
|
||||||
|
emit backLeftErrorChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse backLeftError" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == backRightErrorCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
uint8_t val = value.toShort(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_backRightError = val;
|
||||||
|
emit backRightErrorChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse backRightError" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == frontLeftSpeedCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_frontLeftSpeed = val;
|
||||||
|
emit frontLeftSpeedChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse frontLeftSpeed" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == frontRightSpeedCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_frontRightSpeed = val;
|
||||||
|
emit frontRightSpeedChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse frontRightSpeed" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == backLeftSpeedCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_backLeftSpeed = val;
|
||||||
|
emit backLeftSpeedChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse backLeftSpeed" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == backRightSpeedCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_backRightSpeed = val;
|
||||||
|
emit backRightSpeedChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse backRightSpeed" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == frontLeftDcLinkCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_frontLeftDcLink = val;
|
||||||
|
emit frontLeftDcLinkChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse frontLeftDcLink" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == frontRightDcLinkCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_frontRightDcLink = val;
|
||||||
|
emit frontRightDcLinkChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse frontRightDcLink" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == backLeftDcLinkCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_backLeftDcLink = val;
|
||||||
|
emit backLeftDcLinkChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse backLeftDcLink" << value;
|
||||||
|
}
|
||||||
|
else if (c.uuid() == backRightDcLinkCharacUuid)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
float val = value.toFloat(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_backRightDcLink = val;
|
||||||
|
emit backRightDcLinkChanged();
|
||||||
|
}
|
||||||
|
else if (!value.isEmpty())
|
||||||
|
qWarning() << "could not parse backRightDcLink" << value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandler::confirmedDescriptorWrite(const QLowEnergyDescriptor &d, const QByteArray &value)
|
void DeviceHandler::confirmedDescriptorWrite(const QLowEnergyDescriptor &d, const QByteArray &value)
|
||||||
{
|
{
|
||||||
if (d.isValid() && d == m_notificationDesc && value == QByteArray::fromHex("0000")) {
|
qDebug() << "confirmedDescriptorWrite" << d.uuid() << value;
|
||||||
//disabled notifications -> assume disconnect intent
|
if (d.isValid() && value == QByteArray::fromHex("0000"))
|
||||||
m_control->disconnectFromDevice();
|
{
|
||||||
delete m_service;
|
if (d == m_notificationDescFrontVoltage)
|
||||||
m_service = nullptr;
|
m_notificationDescFrontVoltage = {};
|
||||||
|
if (d == m_notificationDescBackVoltage)
|
||||||
|
m_notificationDescBackVoltage = {};
|
||||||
|
if (d == m_notificationDescFrontTemperature)
|
||||||
|
m_notificationDescFrontTemperature = {};
|
||||||
|
if (d == m_notificationDescBackTemperature)
|
||||||
|
m_notificationDescBackTemperature = {};
|
||||||
|
if (d == m_notificationDescFrontLeftError)
|
||||||
|
m_notificationDescFrontLeftError = {};
|
||||||
|
if (d == m_notificationDescFrontRightError)
|
||||||
|
m_notificationDescFrontRightError = {};
|
||||||
|
if (d == m_notificationDescBackLeftError)
|
||||||
|
m_notificationDescBackLeftError = {};
|
||||||
|
if (d == m_notificationDescBackRightError)
|
||||||
|
m_notificationDescBackRightError = {};
|
||||||
|
if (d == m_notificationDescFrontLeftSpeed)
|
||||||
|
m_notificationDescFrontLeftSpeed = {};
|
||||||
|
if (d == m_notificationDescFrontRightSpeed)
|
||||||
|
m_notificationDescFrontRightSpeed = {};
|
||||||
|
if (d == m_notificationDescBackLeftSpeed)
|
||||||
|
m_notificationDescBackLeftSpeed = {};
|
||||||
|
if (d == m_notificationDescBackRightSpeed)
|
||||||
|
m_notificationDescBackRightSpeed = {};
|
||||||
|
if (d == m_notificationDescFrontLeftDcLink)
|
||||||
|
m_notificationDescFrontLeftDcLink = {};
|
||||||
|
if (d == m_notificationDescFrontRightDcLink)
|
||||||
|
m_notificationDescFrontRightDcLink = {};
|
||||||
|
if (d == m_notificationDescBackLeftDcLink)
|
||||||
|
m_notificationDescBackLeftDcLink = {};
|
||||||
|
if (d == m_notificationDescBackRightDcLink)
|
||||||
|
m_notificationDescBackRightDcLink = {};
|
||||||
|
|
||||||
|
disconnectInternal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,21 +631,74 @@ void DeviceHandler::disconnectService()
|
|||||||
m_foundBobbycarService = false;
|
m_foundBobbycarService = false;
|
||||||
|
|
||||||
//disable notifications
|
//disable notifications
|
||||||
if (m_notificationDesc.isValid() && m_service
|
if (m_service)
|
||||||
&& m_notificationDesc.value() == QByteArray::fromHex("0100")) {
|
{
|
||||||
m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0000"));
|
if (m_notificationDescFrontVoltage.isValid() && m_notificationDescFrontVoltage.value() == QByteArray::fromHex("0100"))
|
||||||
} else {
|
m_service->writeDescriptor(m_notificationDescFrontVoltage, QByteArray::fromHex("0000"));
|
||||||
if (m_control)
|
if (m_notificationDescBackVoltage.isValid() && m_notificationDescBackVoltage.value() == QByteArray::fromHex("0100"))
|
||||||
m_control->disconnectFromDevice();
|
m_service->writeDescriptor(m_notificationDescBackVoltage, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescFrontTemperature.isValid() && m_notificationDescFrontTemperature.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontTemperature, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescBackTemperature.isValid() && m_notificationDescBackTemperature.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackTemperature, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescFrontLeftError.isValid() && m_notificationDescFrontLeftError.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontLeftError, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescFrontRightError.isValid() && m_notificationDescFrontRightError.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontRightError, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescBackLeftError.isValid() && m_notificationDescBackLeftError.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackLeftError, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescBackRightError.isValid() && m_notificationDescBackRightError.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackRightError, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescFrontLeftSpeed.isValid() && m_notificationDescFrontLeftSpeed.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontLeftSpeed, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescFrontRightSpeed.isValid() && m_notificationDescFrontRightSpeed.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontRightSpeed, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescBackLeftSpeed.isValid() && m_notificationDescBackLeftSpeed.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackLeftSpeed, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescBackRightSpeed.isValid() && m_notificationDescBackRightSpeed.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackRightSpeed, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescFrontLeftDcLink.isValid() && m_notificationDescFrontLeftDcLink.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontLeftDcLink, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescFrontRightDcLink.isValid() && m_notificationDescFrontRightDcLink.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescFrontRightDcLink, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescBackLeftDcLink.isValid() && m_notificationDescBackLeftDcLink.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackLeftDcLink, QByteArray::fromHex("0000"));
|
||||||
|
if (m_notificationDescBackRightDcLink.isValid() && m_notificationDescBackRightDcLink.value() == QByteArray::fromHex("0100"))
|
||||||
|
m_service->writeDescriptor(m_notificationDescBackRightDcLink, QByteArray::fromHex("0000"));
|
||||||
|
|
||||||
delete m_service;
|
disconnectInternal();
|
||||||
m_service = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceHandler::measuring() const
|
void DeviceHandler::disconnectInternal()
|
||||||
{
|
{
|
||||||
return m_measuring;
|
if (!m_notificationDescFrontVoltage.isValid() &&
|
||||||
|
!m_notificationDescBackVoltage.isValid() &&
|
||||||
|
!m_notificationDescFrontTemperature.isValid() &&
|
||||||
|
!m_notificationDescBackTemperature.isValid() &&
|
||||||
|
!m_notificationDescFrontLeftError.isValid() &&
|
||||||
|
!m_notificationDescFrontRightError.isValid() &&
|
||||||
|
!m_notificationDescBackLeftError.isValid() &&
|
||||||
|
!m_notificationDescBackRightError.isValid() &&
|
||||||
|
!m_notificationDescFrontLeftSpeed.isValid() &&
|
||||||
|
!m_notificationDescFrontRightSpeed.isValid() &&
|
||||||
|
!m_notificationDescBackLeftSpeed.isValid() &&
|
||||||
|
!m_notificationDescBackRightSpeed.isValid() &&
|
||||||
|
!m_notificationDescFrontLeftDcLink.isValid() &&
|
||||||
|
!m_notificationDescFrontRightDcLink.isValid() &&
|
||||||
|
!m_notificationDescBackLeftDcLink.isValid() &&
|
||||||
|
!m_notificationDescBackRightDcLink.isValid())
|
||||||
|
{
|
||||||
|
//disabled notifications -> assume disconnect intent
|
||||||
|
if (m_control)
|
||||||
|
m_control->disconnectFromDevice();
|
||||||
|
|
||||||
|
if (m_service)
|
||||||
|
{
|
||||||
|
delete m_service;
|
||||||
|
m_service = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeviceHandler::alive() const
|
bool DeviceHandler::alive() const
|
||||||
@@ -221,28 +708,3 @@ bool DeviceHandler::alive() const
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeviceHandler::time() const
|
|
||||||
{
|
|
||||||
return m_start.secsTo(m_stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceHandler::addMeasurement(float value)
|
|
||||||
{
|
|
||||||
m_currentValue = value;
|
|
||||||
|
|
||||||
// If measuring and value is appropriate
|
|
||||||
if (m_measuring) {
|
|
||||||
|
|
||||||
m_stop = QDateTime::currentDateTime();
|
|
||||||
m_measurements << value;
|
|
||||||
|
|
||||||
m_min = m_min == 0 ? value : qMin(value, m_min);
|
|
||||||
m_max = qMax(value, m_max);
|
|
||||||
m_sum += value;
|
|
||||||
m_avg = (double)m_sum / m_measurements.size();
|
|
||||||
m_distance += value * 1000.f * 3600;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit statsChanged();
|
|
||||||
}
|
|
||||||
|
122
devicehandler.h
122
devicehandler.h
@@ -15,16 +15,24 @@ class DeviceInfo;
|
|||||||
class DeviceHandler : public BluetoothBaseClass
|
class DeviceHandler : public BluetoothBaseClass
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(bool measuring READ measuring NOTIFY measuringChanged)
|
|
||||||
Q_PROPERTY(bool alive READ alive NOTIFY aliveChanged)
|
|
||||||
Q_PROPERTY(float speed READ speed NOTIFY statsChanged)
|
|
||||||
Q_PROPERTY(float maxSpeed READ maxSpeed NOTIFY statsChanged)
|
|
||||||
Q_PROPERTY(float minSpeed READ minSpeed NOTIFY statsChanged)
|
|
||||||
Q_PROPERTY(float avgSpeed READ avgSpeed NOTIFY statsChanged)
|
|
||||||
Q_PROPERTY(int time READ time NOTIFY statsChanged)
|
|
||||||
Q_PROPERTY(float distance READ distance NOTIFY statsChanged)
|
|
||||||
Q_PROPERTY(AddressType addressType READ addressType WRITE setAddressType)
|
Q_PROPERTY(AddressType addressType READ addressType WRITE setAddressType)
|
||||||
|
Q_PROPERTY(bool alive READ alive NOTIFY aliveChanged)
|
||||||
|
Q_PROPERTY(float frontVoltage READ frontVoltage NOTIFY frontVoltageChanged);
|
||||||
|
Q_PROPERTY(float backVoltage READ backVoltage NOTIFY backVoltageChanged);
|
||||||
|
Q_PROPERTY(float frontTemperature READ frontTemperature NOTIFY frontTemperatureChanged);
|
||||||
|
Q_PROPERTY(float backTemperature READ backTemperature NOTIFY backTemperatureChanged);
|
||||||
|
Q_PROPERTY(int frontLeftError READ frontLeftError NOTIFY frontLeftErrorChanged);
|
||||||
|
Q_PROPERTY(int frontRightError READ frontRightError NOTIFY frontRightErrorChanged);
|
||||||
|
Q_PROPERTY(int backLeftError READ backLeftError NOTIFY backLeftErrorChanged);
|
||||||
|
Q_PROPERTY(int backRightError READ backRightError NOTIFY backRightErrorChanged);
|
||||||
|
Q_PROPERTY(float frontLeftSpeed READ frontLeftSpeed NOTIFY frontLeftSpeedChanged);
|
||||||
|
Q_PROPERTY(float frontRightSpeed READ frontRightSpeed NOTIFY frontRightSpeedChanged);
|
||||||
|
Q_PROPERTY(float backLeftSpeed READ backLeftSpeed NOTIFY backLeftSpeedChanged);
|
||||||
|
Q_PROPERTY(float backRightSpeed READ backRightSpeed NOTIFY backRightSpeedChanged);
|
||||||
|
Q_PROPERTY(float frontLeftDcLink READ frontLeftDcLink NOTIFY frontLeftDcLinkChanged);
|
||||||
|
Q_PROPERTY(float frontRightDcLink READ frontRightDcLink NOTIFY frontRightDcLinkChanged);
|
||||||
|
Q_PROPERTY(float backLeftDcLink READ backLeftDcLink NOTIFY backLeftDcLinkChanged);
|
||||||
|
Q_PROPERTY(float backRightDcLink READ backRightDcLink NOTIFY backRightDcLinkChanged);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class AddressType {
|
enum class AddressType {
|
||||||
@@ -39,28 +47,51 @@ public:
|
|||||||
void setAddressType(AddressType type);
|
void setAddressType(AddressType type);
|
||||||
AddressType addressType() const;
|
AddressType addressType() const;
|
||||||
|
|
||||||
bool measuring() const;
|
|
||||||
bool alive() const;
|
bool alive() const;
|
||||||
|
|
||||||
// Statistics
|
float frontVoltage() const { return m_frontVoltage; }
|
||||||
float speed() const { return m_currentValue; }
|
float backVoltage() const { return m_backVoltage; }
|
||||||
int time() const;
|
float frontTemperature() const { return m_frontTemperature; }
|
||||||
float avgSpeed() const { return m_avg; }
|
float backTemperature() const { return m_backTemperature; }
|
||||||
float maxSpeed() const { return m_max; }
|
int frontLeftError() const { return m_frontLeftError; }
|
||||||
float minSpeed() const { return m_min; }
|
int frontRightError() const { return m_frontRightError; }
|
||||||
float distance() const { return m_distance; }
|
int backLeftError() const { return m_backLeftError; }
|
||||||
|
int backRightError() const { return m_backRightError; }
|
||||||
|
float frontLeftSpeed() const { return m_frontLeftSpeed; }
|
||||||
|
float frontRightSpeed() const { return m_frontRightSpeed; }
|
||||||
|
float backLeftSpeed() const { return m_backLeftSpeed; }
|
||||||
|
float backRightSpeed() const { return m_backRightSpeed; }
|
||||||
|
float frontLeftDcLink() const { return m_frontLeftDcLink; }
|
||||||
|
float frontRightDcLink() const { return m_frontRightDcLink; }
|
||||||
|
float backLeftDcLink() const { return m_backLeftDcLink; }
|
||||||
|
float backRightDcLink() const { return m_backRightDcLink; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void measuringChanged();
|
|
||||||
void aliveChanged();
|
void aliveChanged();
|
||||||
void statsChanged();
|
|
||||||
|
void frontVoltageChanged();
|
||||||
|
void backVoltageChanged();
|
||||||
|
void frontTemperatureChanged();
|
||||||
|
void backTemperatureChanged();
|
||||||
|
void frontLeftErrorChanged();
|
||||||
|
void frontRightErrorChanged();
|
||||||
|
void backLeftErrorChanged();
|
||||||
|
void backRightErrorChanged();
|
||||||
|
void frontLeftSpeedChanged();
|
||||||
|
void frontRightSpeedChanged();
|
||||||
|
void backLeftSpeedChanged();
|
||||||
|
void backRightSpeedChanged();
|
||||||
|
void frontLeftDcLinkChanged();
|
||||||
|
void frontRightDcLinkChanged();
|
||||||
|
void backLeftDcLinkChanged();
|
||||||
|
void backRightDcLinkChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void startMeasurement();
|
|
||||||
void stopMeasurement();
|
|
||||||
void disconnectService();
|
void disconnectService();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void disconnectInternal();
|
||||||
|
|
||||||
//QLowEnergyController
|
//QLowEnergyController
|
||||||
void serviceDiscovered(const QBluetoothUuid &);
|
void serviceDiscovered(const QBluetoothUuid &);
|
||||||
void serviceScanDone();
|
void serviceScanDone();
|
||||||
@@ -73,24 +104,45 @@ private:
|
|||||||
const QByteArray &value);
|
const QByteArray &value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addMeasurement(float value);
|
QLowEnergyController::RemoteAddressType m_addressType = QLowEnergyController::PublicAddress;
|
||||||
|
|
||||||
QLowEnergyController *m_control = nullptr;
|
QLowEnergyController *m_control = nullptr;
|
||||||
QLowEnergyService *m_service = nullptr;
|
QLowEnergyService *m_service = nullptr;
|
||||||
QLowEnergyDescriptor m_notificationDesc;
|
QLowEnergyDescriptor m_notificationDescFrontVoltage;
|
||||||
DeviceInfo *m_currentDevice = nullptr;
|
QLowEnergyDescriptor m_notificationDescBackVoltage;
|
||||||
|
QLowEnergyDescriptor m_notificationDescFrontTemperature;
|
||||||
|
QLowEnergyDescriptor m_notificationDescBackTemperature;
|
||||||
|
QLowEnergyDescriptor m_notificationDescFrontLeftError;
|
||||||
|
QLowEnergyDescriptor m_notificationDescFrontRightError;
|
||||||
|
QLowEnergyDescriptor m_notificationDescBackLeftError;
|
||||||
|
QLowEnergyDescriptor m_notificationDescBackRightError;
|
||||||
|
QLowEnergyDescriptor m_notificationDescFrontLeftSpeed;
|
||||||
|
QLowEnergyDescriptor m_notificationDescFrontRightSpeed;
|
||||||
|
QLowEnergyDescriptor m_notificationDescBackLeftSpeed;
|
||||||
|
QLowEnergyDescriptor m_notificationDescBackRightSpeed;
|
||||||
|
QLowEnergyDescriptor m_notificationDescFrontLeftDcLink;
|
||||||
|
QLowEnergyDescriptor m_notificationDescFrontRightDcLink;
|
||||||
|
QLowEnergyDescriptor m_notificationDescBackLeftDcLink;
|
||||||
|
QLowEnergyDescriptor m_notificationDescBackRightDcLink;
|
||||||
|
DeviceInfo *m_currentDevice{};
|
||||||
|
|
||||||
bool m_foundBobbycarService;
|
bool m_foundBobbycarService{};
|
||||||
bool m_measuring;
|
|
||||||
float m_currentValue, m_min, m_max, m_sum;
|
|
||||||
float m_avg, m_distance;
|
|
||||||
|
|
||||||
// Statistics
|
float m_frontVoltage{};
|
||||||
QDateTime m_start;
|
float m_backVoltage{};
|
||||||
QDateTime m_stop;
|
float m_frontTemperature{};
|
||||||
|
float m_backTemperature{};
|
||||||
QVector<float> m_measurements;
|
uint8_t m_frontLeftError{};
|
||||||
QLowEnergyController::RemoteAddressType m_addressType = QLowEnergyController::PublicAddress;
|
uint8_t m_frontRightError{};
|
||||||
|
uint8_t m_backLeftError{};
|
||||||
|
uint8_t m_backRightError{};
|
||||||
|
float m_frontLeftSpeed{};
|
||||||
|
float m_frontRightSpeed{};
|
||||||
|
float m_backLeftSpeed{};
|
||||||
|
float m_backRightSpeed;
|
||||||
|
float m_frontLeftDcLink{};
|
||||||
|
float m_frontRightDcLink{};
|
||||||
|
float m_backLeftDcLink{};
|
||||||
|
float m_backRightDcLink{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DEVICEHANDLER_H
|
#endif // DEVICEHANDLER_H
|
||||||
|
2
main.cpp
2
main.cpp
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
|
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
|
||||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
5
qml.qrc
5
qml.qrc
@@ -7,8 +7,9 @@
|
|||||||
<file>qml/App.qml</file>
|
<file>qml/App.qml</file>
|
||||||
<file>qml/TitleBar.qml</file>
|
<file>qml/TitleBar.qml</file>
|
||||||
<file>qml/Connect.qml</file>
|
<file>qml/Connect.qml</file>
|
||||||
<file>qml/Measure.qml</file>
|
<file>qml/Livedata.qml</file>
|
||||||
<file>qml/Stats.qml</file>
|
<file>qml/LivedataMotor.qml</file>
|
||||||
|
<file>qml/RemoteControl.qml</file>
|
||||||
<file>qml/GameButton.qml</file>
|
<file>qml/GameButton.qml</file>
|
||||||
<file>qml/GamePage.qml</file>
|
<file>qml/GamePage.qml</file>
|
||||||
<file>qml/BottomLine.qml</file>
|
<file>qml/BottomLine.qml</file>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: app
|
id: app
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
import Shared 1.0
|
import Shared 1.0
|
||||||
|
|
||||||
GamePage {
|
GamePage {
|
||||||
@@ -57,7 +57,7 @@ GamePage {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
deviceFinder.connectToService(modelData.deviceAddress);
|
deviceFinder.connectToService(modelData.deviceAddress);
|
||||||
app.showPage("Measure.qml")
|
app.showPage("Livedata.qml")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
import "."
|
import "."
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
import "."
|
import "."
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
property int wHeight
|
property int wHeight
|
||||||
|
208
qml/Livedata.qml
Normal file
208
qml/Livedata.qml
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
|
||||||
|
GamePage {
|
||||||
|
id: livedatePage
|
||||||
|
|
||||||
|
errorMessage: deviceHandler.error
|
||||||
|
infoMessage: deviceHandler.info
|
||||||
|
|
||||||
|
property real avgSpeed: (deviceHandler.frontLeftSpeed + deviceHandler.frontRightSpeed + deviceHandler.backLeftSpeed + deviceHandler.backRightSpeed) / 4
|
||||||
|
property real avgVoltage: (deviceHandler.frontVoltage + deviceHandler.backVoltage) / 2
|
||||||
|
property real totalCurrent: deviceHandler.frontLeftDcLink + deviceHandler.frontRightDcLink + deviceHandler.backLeftDcLink + deviceHandler.backRightDcLink
|
||||||
|
property real totalPower: totalCurrent * avgVoltage
|
||||||
|
|
||||||
|
function close()
|
||||||
|
{
|
||||||
|
deviceHandler.disconnectService();
|
||||||
|
app.prevPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: container
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: Math.min(livedatePage.width, livedatePage.height-GameSettings.fieldHeight*4) - 2*GameSettings.fieldMargin
|
||||||
|
height: livedatePage.height-GameSettings.fieldHeight*4
|
||||||
|
radius: GameSettings.buttonRadius
|
||||||
|
color: GameSettings.viewColor
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: flickable
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
//spacing: GameSettings.buttonRadius
|
||||||
|
|
||||||
|
contentWidth: contentColumn.width
|
||||||
|
contentHeight: contentColumn.height
|
||||||
|
flickableDirection: Flickable.VerticalFlick
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: contentColumn
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
font.pixelSize: GameSettings.hugeFontSize * 2
|
||||||
|
color: GameSettings.textColor
|
||||||
|
text: Number(avgSpeed).toLocaleString(Qt.locale()) + 'km/h'
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
font.pixelSize: GameSettings.hugeFontSize * 2
|
||||||
|
color: GameSettings.textColor
|
||||||
|
text: Number(totalCurrent).toLocaleString(Qt.locale()) + 'A'
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
font.pixelSize: GameSettings.hugeFontSize * 2
|
||||||
|
color: GameSettings.textColor
|
||||||
|
text: Number(totalPower>1000?(totalPower/1000):totalPower).toLocaleString(Qt.locale()) + (totalPower > 1000 ? "kW" : "W")
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: "Front: " + Number(deviceHandler.frontVoltage).toLocaleString(Qt.locale()) + "V / " + Number(deviceHandler.frontTemperature).toLocaleString(Qt.locale()) + "°C"
|
||||||
|
color: GameSettings.textColor
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
columns: 2
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
LivedataMotor {
|
||||||
|
width: (container.width/2)-10;
|
||||||
|
|
||||||
|
error: deviceHandler.frontLeftError
|
||||||
|
speed: deviceHandler.frontLeftSpeed
|
||||||
|
dcLink: deviceHandler.frontLeftDcLink
|
||||||
|
voltage: deviceHandler.frontVoltage
|
||||||
|
}
|
||||||
|
|
||||||
|
LivedataMotor {
|
||||||
|
width: (container.width/2)-10;
|
||||||
|
|
||||||
|
error: deviceHandler.frontRightError
|
||||||
|
speed: deviceHandler.frontRightSpeed
|
||||||
|
dcLink: deviceHandler.frontRightDcLink
|
||||||
|
voltage: deviceHandler.frontVoltage
|
||||||
|
}
|
||||||
|
|
||||||
|
LivedataMotor {
|
||||||
|
width: (container.width/2)-10;
|
||||||
|
|
||||||
|
error: deviceHandler.backLeftError
|
||||||
|
speed: deviceHandler.backLeftSpeed
|
||||||
|
dcLink: deviceHandler.backLeftDcLink
|
||||||
|
voltage: deviceHandler.backVoltage
|
||||||
|
}
|
||||||
|
|
||||||
|
LivedataMotor {
|
||||||
|
width: (container.width/2)-10;
|
||||||
|
|
||||||
|
error: deviceHandler.backRightError
|
||||||
|
speed: deviceHandler.backRightSpeed
|
||||||
|
dcLink: deviceHandler.backRightDcLink
|
||||||
|
voltage: deviceHandler.backVoltage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: "Back: " + Number(deviceHandler.backVoltage).toLocaleString(Qt.locale()) + "V / " + Number(deviceHandler.backTemperature).toLocaleString(Qt.locale()) + "°C"
|
||||||
|
//visible: deviceHandler.alive
|
||||||
|
color: GameSettings.textColor
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: bobbycar
|
||||||
|
//anchors.horizontalCenter: flickable.horizontalCenter
|
||||||
|
//anchors.verticalCenter: flickable.bottom
|
||||||
|
width: parent.width * 0.2
|
||||||
|
height: width
|
||||||
|
source: "images/logo.png"
|
||||||
|
smooth: true
|
||||||
|
antialiasing: true
|
||||||
|
|
||||||
|
SequentialAnimation{
|
||||||
|
id: bobbycarAnim
|
||||||
|
running: deviceHandler.alive
|
||||||
|
loops: Animation.Infinite
|
||||||
|
alwaysRunToEnd: true
|
||||||
|
PropertyAnimation { target: bobbycar; property: "scale"; to: 1.2; duration: 500; easing.type: Easing.InQuad }
|
||||||
|
PropertyAnimation { target: bobbycar; property: "scale"; to: 1.0; duration: 500; easing.type: Easing.OutQuad }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
Label {
|
||||||
|
text: 'iMotMax:'
|
||||||
|
color: GameSettings.textColor
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
|
||||||
|
SpinBox {
|
||||||
|
value: 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
Label {
|
||||||
|
text: 'iDcMax:'
|
||||||
|
color: GameSettings.textColor
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
|
||||||
|
SpinBox {
|
||||||
|
value: 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: 20
|
||||||
|
Text {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: "Placeholder"
|
||||||
|
//visible: deviceHandler.alive
|
||||||
|
color: GameSettings.textColor
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GameButton {
|
||||||
|
id: startButton
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: GameSettings.fieldMargin
|
||||||
|
width: container.width
|
||||||
|
height: GameSettings.fieldHeight
|
||||||
|
radius: GameSettings.buttonRadius
|
||||||
|
|
||||||
|
onClicked: app.showPage("RemoteControl.qml")
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.pixelSize: GameSettings.tinyFontSize
|
||||||
|
text: qsTr("REMOTE")
|
||||||
|
color: startButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
qml/LivedataMotor.qml
Normal file
54
qml/LivedataMotor.qml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import QtQuick 2.15
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
color: GameSettings.delegate1Color
|
||||||
|
height: width*0.8
|
||||||
|
|
||||||
|
property int error;
|
||||||
|
property real speed;
|
||||||
|
property real dcLink;
|
||||||
|
property real voltage;
|
||||||
|
property real power: voltage * dcLink;
|
||||||
|
|
||||||
|
Column {
|
||||||
|
Text {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: ["OK", "HALL miss", "HALL short", "MOTOR"][error] + " (" + error + ")";
|
||||||
|
color: error == 0 ? "green" : "red"
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: Number(speed).toLocaleString(Qt.locale()) + "km/h"
|
||||||
|
color: GameSettings.textColor
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: Number(dcLink).toLocaleString(Qt.locale()) + "A"
|
||||||
|
color: GameSettings.textColor
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: Number(power>1000?(power/1000):power).toLocaleString(Qt.locale()) + (power > 1000 ? "kW" : "W")
|
||||||
|
color: GameSettings.textColor
|
||||||
|
minimumPixelSize: 10
|
||||||
|
font.pixelSize: GameSettings.mediumFontSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
194
qml/Measure.qml
194
qml/Measure.qml
@@ -1,194 +0,0 @@
|
|||||||
import QtQuick 2.5
|
|
||||||
|
|
||||||
GamePage {
|
|
||||||
id: measurePage
|
|
||||||
|
|
||||||
errorMessage: deviceHandler.error
|
|
||||||
infoMessage: deviceHandler.info
|
|
||||||
|
|
||||||
property real __timeCounter: 0;
|
|
||||||
property real __maxTimeCount: 60
|
|
||||||
property string relaxText: qsTr("FAST!\nWhen you are ready, press Start. You have %1s time to increase speed so much as possible.\nGood luck!").arg(__maxTimeCount)
|
|
||||||
|
|
||||||
function close()
|
|
||||||
{
|
|
||||||
deviceHandler.stopMeasurement();
|
|
||||||
deviceHandler.disconnectService();
|
|
||||||
app.prevPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
function start()
|
|
||||||
{
|
|
||||||
if (!deviceHandler.measuring) {
|
|
||||||
__timeCounter = 0;
|
|
||||||
deviceHandler.startMeasurement()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function stop()
|
|
||||||
{
|
|
||||||
if (deviceHandler.measuring) {
|
|
||||||
deviceHandler.stopMeasurement()
|
|
||||||
}
|
|
||||||
|
|
||||||
app.showPage("Stats.qml")
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: measureTimer
|
|
||||||
interval: 1000
|
|
||||||
running: deviceHandler.measuring
|
|
||||||
repeat: true
|
|
||||||
onTriggered: {
|
|
||||||
__timeCounter++;
|
|
||||||
if (__timeCounter >= __maxTimeCount)
|
|
||||||
measurePage.stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: GameSettings.fieldHeight * 0.5
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: circle
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
width: Math.min(measurePage.width, measurePage.height-GameSettings.fieldHeight*4) - 2*GameSettings.fieldMargin
|
|
||||||
height: width
|
|
||||||
radius: width*0.5
|
|
||||||
color: GameSettings.viewColor
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: hintText
|
|
||||||
anchors.centerIn: parent
|
|
||||||
anchors.verticalCenterOffset: -parent.height*0.1
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
width: parent.width * 0.8
|
|
||||||
height: parent.height * 0.6
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
text: measurePage.relaxText
|
|
||||||
visible: !deviceHandler.measuring
|
|
||||||
color: GameSettings.textColor
|
|
||||||
fontSizeMode: Text.Fit
|
|
||||||
minimumPixelSize: 10
|
|
||||||
font.pixelSize: GameSettings.mediumFontSize
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: text
|
|
||||||
anchors.centerIn: parent
|
|
||||||
anchors.verticalCenterOffset: -parent.height*0.15
|
|
||||||
font.pixelSize: parent.width * 0.45
|
|
||||||
text: deviceHandler.speed.toFixed(0)
|
|
||||||
visible: deviceHandler.measuring
|
|
||||||
color: GameSettings.textColor
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: minMaxContainer
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
width: parent.width*0.7
|
|
||||||
height: parent.height * 0.15
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: parent.height*0.16
|
|
||||||
visible: deviceHandler.measuring
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: deviceHandler.minSpeed.toFixed(0)
|
|
||||||
color: GameSettings.textColor
|
|
||||||
font.pixelSize: GameSettings.hugeFontSize
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.bottom: parent.top
|
|
||||||
font.pixelSize: parent.font.pixelSize*0.8
|
|
||||||
color: parent.color
|
|
||||||
text: "MIN"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
text: deviceHandler.maxSpeed.toFixed(0)
|
|
||||||
color: GameSettings.textColor
|
|
||||||
font.pixelSize: GameSettings.hugeFontSize
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.top
|
|
||||||
font.pixelSize: parent.font.pixelSize*0.8
|
|
||||||
color: parent.color
|
|
||||||
text: "MAX"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: bobbycar
|
|
||||||
anchors.horizontalCenter: minMaxContainer.horizontalCenter
|
|
||||||
anchors.verticalCenter: minMaxContainer.bottom
|
|
||||||
width: parent.width * 0.2
|
|
||||||
height: width
|
|
||||||
source: "images/logo.png"
|
|
||||||
smooth: true
|
|
||||||
antialiasing: true
|
|
||||||
|
|
||||||
SequentialAnimation{
|
|
||||||
id: bobbycarAnim
|
|
||||||
running: deviceHandler.alive
|
|
||||||
loops: Animation.Infinite
|
|
||||||
alwaysRunToEnd: true
|
|
||||||
PropertyAnimation { target: bobbycar; property: "scale"; to: 1.2; duration: 500; easing.type: Easing.InQuad }
|
|
||||||
PropertyAnimation { target: bobbycar; property: "scale"; to: 1.0; duration: 500; easing.type: Easing.OutQuad }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: timeSlider
|
|
||||||
color: GameSettings.viewColor
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
width: circle.width
|
|
||||||
height: GameSettings.fieldHeight
|
|
||||||
radius: GameSettings.buttonRadius
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
height: parent.height
|
|
||||||
radius: parent.radius
|
|
||||||
color: GameSettings.sliderColor
|
|
||||||
width: Math.min(1.0,__timeCounter / __maxTimeCount) * parent.width
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
color: "gray"
|
|
||||||
text: (__maxTimeCount - __timeCounter).toFixed(0) + " s"
|
|
||||||
font.pixelSize: GameSettings.bigFontSize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GameButton {
|
|
||||||
id: startButton
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: GameSettings.fieldMargin
|
|
||||||
width: circle.width
|
|
||||||
height: GameSettings.fieldHeight
|
|
||||||
enabled: !deviceHandler.measuring
|
|
||||||
radius: GameSettings.buttonRadius
|
|
||||||
|
|
||||||
onClicked: start()
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
font.pixelSize: GameSettings.tinyFontSize
|
|
||||||
text: qsTr("START")
|
|
||||||
color: startButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
40
qml/RemoteControl.qml
Normal file
40
qml/RemoteControl.qml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import QtQuick 2.15
|
||||||
|
|
||||||
|
GamePage {
|
||||||
|
id: remoteControlPage
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.bottom: container.top
|
||||||
|
anchors.bottomMargin: GameSettings.fieldMargin
|
||||||
|
|
||||||
|
font.pixelSize: GameSettings.hugeFontSize
|
||||||
|
color: GameSettings.textColor
|
||||||
|
text: qsTr("REMOTE CONTROL")
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: container
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: Math.min(remoteControlPage.width, remoteControlPage.height-GameSettings.fieldHeight*4) - 2*GameSettings.fieldMargin
|
||||||
|
height: width
|
||||||
|
radius: GameSettings.buttonRadius
|
||||||
|
color: GameSettings.viewColor
|
||||||
|
|
||||||
|
PointHandler {
|
||||||
|
id: handler
|
||||||
|
//acceptedDevices: PointerDevice.TouchScreen
|
||||||
|
target: Rectangle {
|
||||||
|
parent: container
|
||||||
|
color: "red"
|
||||||
|
visible: handler.active
|
||||||
|
x: handler.point.position.x - width / 2
|
||||||
|
y: handler.point.position.y - height / 2
|
||||||
|
width: 20
|
||||||
|
height: width
|
||||||
|
radius: width / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
import "."
|
import "."
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@@ -1,49 +0,0 @@
|
|||||||
import QtQuick 2.5
|
|
||||||
|
|
||||||
GamePage {
|
|
||||||
|
|
||||||
Column {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: parent.width
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
font.pixelSize: GameSettings.hugeFontSize
|
|
||||||
color: GameSettings.textColor
|
|
||||||
text: qsTr("RESULT")
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
font.pixelSize: GameSettings.giganticFontSize*3
|
|
||||||
color: GameSettings.textColor
|
|
||||||
text: (deviceHandler.maxSpeed - deviceHandler.minSpeed).toFixed(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
height: GameSettings.fieldHeight
|
|
||||||
width: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
StatsLabel {
|
|
||||||
title: qsTr("MIN")
|
|
||||||
value: deviceHandler.minSpeed.toFixed(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
StatsLabel {
|
|
||||||
title: qsTr("MAX")
|
|
||||||
value: deviceHandler.maxSpeed.toFixed(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
StatsLabel {
|
|
||||||
title: qsTr("AVG")
|
|
||||||
value: deviceHandler.avgSpeed.toFixed(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
StatsLabel {
|
|
||||||
title: qsTr("DISTANCE")
|
|
||||||
value: deviceHandler.distance.toFixed(3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
import "."
|
import "."
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import QtQuick 2.5
|
import QtQuick 2.15
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: titleBar
|
id: titleBar
|
||||||
@@ -8,7 +8,7 @@ Rectangle {
|
|||||||
height: GameSettings.fieldHeight
|
height: GameSettings.fieldHeight
|
||||||
color: GameSettings.viewColor
|
color: GameSettings.viewColor
|
||||||
|
|
||||||
property var __titles: ["CONNECT", "MEASURE", "STATS"]
|
property var __titles: ["CONNECT", "LIVEDATA", "REMOTECONTROL"]
|
||||||
property int currentIndex: 0
|
property int currentIndex: 0
|
||||||
|
|
||||||
signal titleClicked(int index)
|
signal titleClicked(int index)
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import QtQuick 2.7
|
import QtQuick 2.15
|
||||||
import QtQuick.Window 2.2
|
import QtQuick.Window 2.15
|
||||||
import "."
|
import "."
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
|
Reference in New Issue
Block a user