EQ-3 plugin: Some fixes for the Eqiva Bluetooth Radiator Thermostat
This commit is contained in:
parent
2ac80c0414
commit
f518c8356a
@ -1,28 +1,38 @@
|
||||
# eQ-3
|
||||
|
||||
This plugin allows to find and control devices from Max!(eQ-3). To use this devices, you need at least
|
||||
one [Max! Cube LAN Gateway](http://www.eq-3.de/max-heizungssteuerung-produktdetail/items/bc-lgw-o-tw.html)
|
||||
in you local network. Once the cube is connected (DHCP), you can auto detect the cube in the network and
|
||||
add it to your [nymea](https://nymea.io) devices. Also more than one cube in the network is supported. All
|
||||
devices, which are connected to a cube, will be autogenerated. For the setup of a cube, the original
|
||||
software is recomanded (min/max setpoint temperature, weekly program...).
|
||||
This plugin allows to find and control radiation equipment by EQ-3.
|
||||
|
||||
## Supported devices
|
||||
Currently supported devices are the [EQ-3 Max! Cube LAN Gateway](http://www.eq-3.de/max-heizungssteuerung-produktdetail/items/bc-lgw-o-tw.html)
|
||||
as well as [Eqiva Bluetooth Smart Radiator Thermostat](https://www.eq-3.com/products/eqiva/bluetooth-smart-radiator-thermostat.html).
|
||||
|
||||
To use this plugin, you need either a Max! Cube LAN Gateway with radiator or wall thermostats connected, or one or more
|
||||
Eqiva Bluetooth Smart Radiator Thermostats within the range of the Bluetooth signal from your nymea system.
|
||||
|
||||
### Eqiva Bluetooth Smart Radiator Thermostat
|
||||
|
||||
In order to use the [Eqiva Bluetooth Smart Radiator Thermostat](https://www.eq-3.com/products/eqiva/bluetooth-smart-radiator-thermostat.html)
|
||||
with nymea, the nymea system is required to have Bluetooth support and the nymea system and the Thermostat need to be located within
|
||||
the range of Bluetooth between each other. Once the thermostat is connected to the radiator and calibrated for it (refer to the
|
||||
Eqiva Smart Bluetooth Radiator Thermostat Manual) it can be added to nymea through the device setup.
|
||||
|
||||
Note: It is recommended to set the Radiator Thermostat mode to "Manual" if nymea should be controlling the target temperature. When the
|
||||
radiator thermostat's mode is set to "Auto", it will manage temperature settings on its own and disregard nymea's commands.
|
||||
|
||||
### Max! Cube LAN Gateway
|
||||
|
||||
This [cube](http://www.eq-3.de/max-heizungssteuerung-produktdetail/items/bc-lgw-o-tw.html) can be discovered in the network. Every device, which is connected with the cube, will be appear automatically, once the cube is configrued and
|
||||
added to nymea.
|
||||
Once the cube is connected to the same network as the nymea system, it can be added to nymea through. Having connected multiple
|
||||
Max! Cubes to the same network is also supported. Thermostats connected to the cube will be automatically detected and added
|
||||
to the nymea system. If using the Max! Cube with nymea, it is recommended to keep the Cube's settings at factory defaults as
|
||||
schedules set up in the Cube will be conflicting with schedules set through nymea.
|
||||
|
||||
### Max! Wall Thermostat
|
||||
|
||||
In order to use this device, you need a [Max! Cube LAN Gateway](http://www.eq-3.de/max-heizungssteuerung-produktdetail/
|
||||
items/bc-lgw-o-tw.html). A [MAX! Wall Thermostat](http://www.eq-3.de/max-raumloesung-produktdetail/items/bc-tc-c-wm.html) can not be added,
|
||||
it will appear automatically in the device list, once you add it to the cube.
|
||||
In order to use a [MAX! Wall Thermostat](http://www.eq-3.de/max-raumloesung-produktdetail/items/bc-tc-c-wm.html) with nymea a
|
||||
Max! Cube LAN Gateway is required. Once the thermostat is connected to the Max! Cube, it will automatically appear in nymea,
|
||||
provided the Cube has been set up in nymea.
|
||||
|
||||
### Max! Radiator Thermostat
|
||||
|
||||
In order to use this device, you need a [Max! Cube LAN Gateway](http://www.eq-3.de/max-heizungssteuerung-produktdetail/
|
||||
items/bc-lgw-o-tw.html). A [MAX! Radiator Thermostat](http://www.eq-3.de/max-heizungssteuerung-produktdetail/items/bc-rt-trx-cyg.html) can not be added,
|
||||
it will appear automatically in the device list, once you add it to the cube.
|
||||
|
||||
In order to use a [MAX! Radiator Thermostat](http://www.eq-3.de/max-heizungssteuerung-produktdetail/items/bc-rt-trx-cyg.html)
|
||||
with nymea a Max! Cube LAN Gateway is required. Once the thermostat is connected to the Max! Cube, it will automatically appear in nymea,
|
||||
provided the Cube has been set up in nymea.
|
||||
|
||||
@ -86,7 +86,6 @@ void DevicePluginEQ3::discoverDevices(DeviceDiscoveryInfo *info)
|
||||
return;
|
||||
}
|
||||
if (deviceClassId == eqivaBluetoothDeviceClassId) {
|
||||
|
||||
EqivaBluetoothDiscovery *eqivaBluetoothDiscovery = new EqivaBluetoothDiscovery(hardwareManager()->bluetoothLowEnergyManager(), this);
|
||||
|
||||
// Clean up the discovery when the DiscoveryInfo goes away...
|
||||
@ -97,7 +96,7 @@ void DevicePluginEQ3::discoverDevices(DeviceDiscoveryInfo *info)
|
||||
qCDebug(dcEQ3()) << "Discovery finished";
|
||||
|
||||
foreach (const QString &result, results) {
|
||||
qCDebug(dcEQ3()) << "Discovered device" << result;
|
||||
qCDebug(dcEQ3()) << "Discovered EQ-3 device" << result;
|
||||
DeviceDescriptor descriptor(eqivaBluetoothDeviceClassId, "Eqiva Bluetooth Thermostat", result);
|
||||
ParamList params;
|
||||
params << Param(eqivaBluetoothDeviceMacAddressParamTypeId, result);
|
||||
@ -207,6 +206,11 @@ void DevicePluginEQ3::setupDevice(DeviceSetupInfo *info)
|
||||
connect(eqivaDevice, &EqivaBluetooth::valveOpenChanged, device, [device, eqivaDevice](){
|
||||
device->setStateValue(eqivaBluetoothValveOpenStateTypeId, eqivaDevice->valveOpen());
|
||||
});
|
||||
// Battery critical state
|
||||
device->setStateValue(eqivaBluetoothBatteryCriticalStateTypeId, eqivaDevice->batteryCritical());
|
||||
connect(eqivaDevice, &EqivaBluetooth::batteryCriticalChanged, device, [device, eqivaDevice](){
|
||||
device->setStateValue(eqivaBluetoothBatteryCriticalStateTypeId, eqivaDevice->batteryCritical());
|
||||
});
|
||||
}
|
||||
|
||||
info->finish(Device::DeviceErrorNoError);
|
||||
@ -335,6 +339,9 @@ void DevicePluginEQ3::executeAction(DeviceActionInfo *info)
|
||||
}
|
||||
|
||||
connect(eqivaDevice, &EqivaBluetooth::commandResult, info, [info, commandId](int commandIdResult, bool success){
|
||||
if (!success) {
|
||||
qCWarning(dcEQ3()) << "Error writing characteristic";
|
||||
}
|
||||
if (commandId == commandIdResult) {
|
||||
info->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareFailure);
|
||||
}
|
||||
|
||||
@ -532,7 +532,7 @@
|
||||
"id": "3c51327b-a823-4479-bd4b-f4ba64267ed8",
|
||||
"name": "eqivaBluetooth",
|
||||
"displayName": "Eqiva Bluetooth Smart Radiator Thermostat",
|
||||
"interfaces": ["heating", "thermostat", "connectable"],
|
||||
"interfaces": ["heating", "thermostat", "connectable", "battery"],
|
||||
"createMethods": ["discovery"],
|
||||
"setupMethod": "JustAdd",
|
||||
"paramTypes": [
|
||||
@ -628,6 +628,14 @@
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
"id": "174f6388-0fbe-4d04-82ea-99c63bcf6f5a",
|
||||
"name": "batteryCritical",
|
||||
"displayName": "Battery critical",
|
||||
"displayNameEvent": "Battery critical changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -5,11 +5,37 @@
|
||||
#include <QDataStream>
|
||||
#include <QDateTime>
|
||||
|
||||
const QBluetoothUuid eqivaServiceUuid = QBluetoothUuid(QString("{3e135142-654f-9090-134a-a6ff5bb77046}"));
|
||||
|
||||
const QBluetoothUuid eqivaCommandServiceUuid = QBluetoothUuid(QString("{3e135142-654f-9090-134a-a6ff5bb77046}"));
|
||||
//I | EQ3: Service discovered: "Unknown Service" "{3e135142-654f-9090-134a-a6ff5bb77046}"
|
||||
//I | EQ3: C: --> {3fa4585a-ce4a-3bad-db4b-b8df8179ea09} (Handle 0x411 Name: ): 0313091e0b2936000000000000000000 )6
|
||||
//I | EQ3: C: --> {d0e8434d-cd29-0996-af41-6c90f4e0eb2a} (Handle 0x421 Name: ): 00000000000000000000000000000000
|
||||
//I | EQ3: D: --> {00002902-0000-1000-8000-00805f9b34fb} (Handle 0x430 Name: Client Characteristic Configuration): 0100
|
||||
const QBluetoothUuid eqivaGapServiceUuid = QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb"));
|
||||
//I | EQ3: Service discovered: "Generic Access" "{00001800-0000-1000-8000-00805f9b34fb}"
|
||||
//I | EQ3: C: --> {00002a00-0000-1000-8000-00805f9b34fb} (Handle 0x111 Name: GAP Device Name): 43432d52542d424c45CC-RT-BLE
|
||||
//I | EQ3: C: --> {00002a01-0000-1000-8000-00805f9b34fb} (Handle 0x121 Name: GAP Appearance): 0000
|
||||
//I | EQ3: C: --> {00002a02-0000-1000-8000-00805f9b34fb} (Handle 0x131 Name: GAP Peripheral Privacy Flag): 00
|
||||
//I | EQ3: C: --> {00002a03-0000-1000-8000-00805f9b34fb} (Handle 0x141 Name: GAP Reconnection Address):
|
||||
//I | EQ3: C: --> {00002a04-0000-1000-8000-00805f9b34fb} (Handle 0x151 Name: GAP Peripheral Preferred Connection Parameters): 0000000000000000
|
||||
const QBluetoothUuid eqivaGattServiceUuid = QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb"));
|
||||
//I | EQ3: Service discovered: "Generic Attribute" "{00001801-0000-1000-8000-00805f9b34fb}"
|
||||
//I | EQ3: C: --> {00002a05-0000-1000-8000-00805f9b34fb} (Handle 0x211 Name: GATT Service Changed): 00000000
|
||||
//I | EQ3: D: --> {00002902-0000-1000-8000-00805f9b34fb} (Handle 0x220 Name: Client Characteristic Configuration): 0200
|
||||
const QBluetoothUuid eqivaDeviceInfoServiceUuid = QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb"));
|
||||
//I | EQ3: Service discovered: "Device Information" "{0000180a-0000-1000-8000-00805f9b34fb}"
|
||||
//I | EQ3: C: --> {00002a29-0000-1000-8000-00805f9b34fb} (Handle 0x311 Name: Manufacturer Name String): 65712d33eq-3
|
||||
//I | EQ3: C: --> {00002a24-0000-1000-8000-00805f9b34fb} (Handle 0x321 Name: Model Number String): 43432d52542d424c45CC-RT-BLE
|
||||
const QBluetoothUuid eqivaUnknownServiceUuid = QBluetoothUuid(QString("9e5d1e47-5c13-43a0-8635-82ad38a1386f"));
|
||||
//I | EQ3: Service discovered: "Unknown Service" "{9e5d1e47-5c13-43a0-8635-82ad38a1386f}"
|
||||
//I | EQ3: C: --> {e3dd50bf-f7a7-4e99-838e-570a086c666b} (Handle 0xff02 Name: ):
|
||||
//I | EQ3: D: --> {00002902-0000-1000-8000-00805f9b34fb} (Handle 0xff03 Name: Client Characteristic Configuration): 0000
|
||||
//I | EQ3: C: --> {92e86c7a-d961-4091-b74f-2409e72efe36} (Handle 0xff05 Name: ):
|
||||
//I | EQ3: C: --> {347f7608-2e2d-47eb-913b-75d4edc4de3b} (Handle 0xff07 Name: ): 00100200
|
||||
|
||||
const QBluetoothUuid commandCharacteristicUuid = QBluetoothUuid(QString("3fa4585a-ce4a-3bad-db4b-b8df8179ea09"));
|
||||
const QBluetoothUuid notificationCharacteristicUuid = QBluetoothUuid(QString("d0e8434d-cd29-0996-af41-6c90f4e0eb2a"));
|
||||
|
||||
const QBluetoothUuid eqivaDeviceInfoServiceUuid = QBluetoothUuid(QString("9e5d1e47-5c13-43a0-8635-82ad38a1386f"));
|
||||
|
||||
// Protocol
|
||||
// Commands:
|
||||
@ -37,14 +63,14 @@ const quint8 modeBoost1 = 0x0C; // at the end it returns to automatic mode
|
||||
const quint8 modeBoost2 = 0x0D; // at the end it returns to manual mode
|
||||
const quint8 modeBoost3 = 0x0E; // at the end it returns to holiday mode
|
||||
|
||||
const quint8 lockOff = 0x00;
|
||||
const quint8 windowLockOn = 0x10;
|
||||
const quint8 keyLockOn = 0x20;
|
||||
const quint8 windowAndKeyOn = 0x30;
|
||||
const quint8 lockOff = 0x00;
|
||||
const quint8 windowLockOn = 0x10;
|
||||
const quint8 keyLockOn = 0x20;
|
||||
const quint8 batteryCriticalOn = 0x80;
|
||||
|
||||
const quint8 setModeAuto = 0x00;
|
||||
const quint8 setModeManual = 0x40;
|
||||
const quint8 setModeHoliday = 0x40; // Same as manual but with a time limit
|
||||
const quint8 setModeAuto = 0x00;
|
||||
const quint8 setModeManual = 0x40;
|
||||
const quint8 setModeHoliday = 0x40; // Same as manual but with a time limit
|
||||
|
||||
EqivaBluetooth::EqivaBluetooth(BluetoothLowEnergyManager *bluetoothManager, const QBluetoothAddress &hostAddress, const QString &name, QObject *parent):
|
||||
QObject(parent),
|
||||
@ -57,7 +83,7 @@ EqivaBluetooth::EqivaBluetooth(BluetoothLowEnergyManager *bluetoothManager, cons
|
||||
connect(m_bluetoothDevice, &BluetoothLowEnergyDevice::stateChanged, this, &EqivaBluetooth::controllerStateChanged);
|
||||
m_bluetoothDevice->connectDevice();
|
||||
|
||||
m_refreshTimer.setInterval(30000);
|
||||
m_refreshTimer.setInterval(5000);
|
||||
m_refreshTimer.setSingleShot(true);
|
||||
connect(&m_refreshTimer, &QTimer::timeout, this, &EqivaBluetooth::sendDate);
|
||||
}
|
||||
@ -175,6 +201,11 @@ quint8 EqivaBluetooth::valveOpen() const
|
||||
return m_valveOpen;
|
||||
}
|
||||
|
||||
bool EqivaBluetooth::batteryCritical() const
|
||||
{
|
||||
return m_batteryCritical;
|
||||
}
|
||||
|
||||
void EqivaBluetooth::controllerStateChanged(const QLowEnergyController::ControllerState &state)
|
||||
{
|
||||
qCDebug(dcEQ3()) << m_name << "Bluetooth device state changed:" << state;
|
||||
@ -201,52 +232,119 @@ void EqivaBluetooth::controllerStateChanged(const QLowEnergyController::Controll
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// DEBUG
|
||||
// qCDebug(dcEQ3()) << m_name << "Discovered: Service UUIDS:" << m_bluetoothDevice->serviceUuids();
|
||||
m_eqivaService = m_bluetoothDevice->controller()->createServiceObject(eqivaServiceUuid, this);
|
||||
// m_eqivaService = m_bluetoothDevice->controller()->createServiceObject(QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb")), this);
|
||||
// m_eqivaService = m_bluetoothDevice->controller()->createServiceObject(QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb")), this);
|
||||
// m_eqivaService = m_bluetoothDevice->controller()->createServiceObject(QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb")), this);
|
||||
// m_eqivaService = m_bluetoothDevice->controller()->createServiceObject(QBluetoothUuid(QString("9e5d1e47-5c13-43a0-8635-82ad38a1386f")), this);
|
||||
connect(m_eqivaService, &QLowEnergyService::stateChanged, this, &EqivaBluetooth::serviceStateChanged);
|
||||
// connect(m_eqivaService, &QLowEnergyService::characteristicRead, this, [](const QLowEnergyCharacteristic &info, const QByteArray &value){
|
||||
// qCDebug(dcEQ3()) << m_name << "Characteristic read:" << info.name() << info.uuid() << value.toHex();
|
||||
// QBluetoothUuid uuid = QBluetoothUuid(QString("{3e135142-654f-9090-134a-a6ff5bb77046}"));
|
||||
//// QBluetoothUuid uuid = QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb"));
|
||||
//// QBluetoothUuid uuid = QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb"));
|
||||
//// QBluetoothUuid uuid = QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb")); // Manufacturer name and model name
|
||||
//// QBluetoothUuid uuid = QBluetoothUuid(QString("9e5d1e47-5c13-43a0-8635-82ad38a1386f"));
|
||||
|
||||
|
||||
// QLowEnergyService *service = m_bluetoothDevice->controller()->createServiceObject(uuid);
|
||||
// service->discoverDetails();
|
||||
// connect(service, &QLowEnergyService::stateChanged, this, [service](QLowEnergyService::ServiceState newState){
|
||||
// if (newState != QLowEnergyService::ServiceDiscovered) {
|
||||
// return;
|
||||
// }
|
||||
// qCDebug(dcEQ3()) << "Service discovered:" << service->serviceName() << service->serviceUuid();
|
||||
// foreach (const QLowEnergyCharacteristic &characteristic, service->characteristics()) {
|
||||
// qCDebug(dcEQ3()).nospace().noquote() << "C: --> " << characteristic.uuid().toString() << " (Handle 0x" << QString("%1").arg(characteristic.handle(), 0, 16) << " Name: " << characteristic.name() << "): 0x" << characteristic.value().toHex() << " " << qUtf8Printable(characteristic.value());
|
||||
// foreach (const QLowEnergyDescriptor &descriptor, characteristic.descriptors()) {
|
||||
// qCDebug(dcEQ3()).nospace().noquote() << "D: --> " << descriptor.uuid().toString() << " (Handle 0x" << QString("%2").arg(descriptor.handle(), 0, 16) << " Name: " << descriptor.name() << "): 0x" << descriptor.value().toHex() << " " << qUtf8Printable(characteristic.value());
|
||||
// }
|
||||
//// service->readCharacteristic(characteristic);
|
||||
// }
|
||||
|
||||
// });
|
||||
// connect(service, &QLowEnergyService::characteristicRead, this, [service](const QLowEnergyCharacteristic &info, const QByteArray &value){
|
||||
// qCDebug(dcEQ3()) << "Characteristic read:" << info.name() << info.uuid() << value.toHex();
|
||||
// });
|
||||
|
||||
// return;
|
||||
// DEBUG END
|
||||
|
||||
m_eqivaService = m_bluetoothDevice->controller()->createServiceObject(eqivaCommandServiceUuid, this);
|
||||
if (!m_eqivaService) {
|
||||
qCWarning(dcEQ3()) << "Failed to create Service Object for service" << eqivaCommandServiceUuid;
|
||||
return;
|
||||
}
|
||||
|
||||
connect(m_eqivaService, &QLowEnergyService::stateChanged, this, &EqivaBluetooth::serviceStateChanged);
|
||||
connect(m_eqivaService, &QLowEnergyService::characteristicRead, this, [this](const QLowEnergyCharacteristic &info, const QByteArray &value){
|
||||
qCDebug(dcEQ3()) << m_name << "Characteristic read:" << info.name() << info.uuid() << value.toHex();
|
||||
|
||||
QByteArray data(value);
|
||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||
quint8 header;
|
||||
stream >> header;
|
||||
quint8 notificationType;
|
||||
stream >> notificationType;
|
||||
quint8 lockAndMode;
|
||||
stream >> lockAndMode;
|
||||
stream >> m_valveOpen;
|
||||
quint8 undefined;
|
||||
stream >> undefined;
|
||||
quint8 rawTemp;
|
||||
stream >> rawTemp;
|
||||
|
||||
qCDebug(dcEQ3()) << "**** header" << header << "type" << notificationType << "lock/mode" << lockAndMode << "valve:" << m_valveOpen << "temp" << rawTemp;
|
||||
|
||||
});
|
||||
connect(m_eqivaService, &QLowEnergyService::characteristicWritten, this, [this](const QLowEnergyCharacteristic &info, const QByteArray &value){
|
||||
qCDebug(dcEQ3()) << m_name << "Characteristic written:" << info.name() << info.uuid() << value.toHex();
|
||||
emit commandResult(m_currentCommand.id, true);
|
||||
m_currentCommand.id = -1;
|
||||
processCommandQueue();
|
||||
// m_eqivaService->readCharacteristic(notificationCharacteristicUuid);
|
||||
});
|
||||
connect(m_eqivaService, &QLowEnergyService::descriptorWritten, this, [this](const QLowEnergyDescriptor &info, const QByteArray &value){
|
||||
qCDebug(dcEQ3()) << m_name << "Descriptor written" << info.uuid() << value;
|
||||
});
|
||||
connect(m_eqivaService, &QLowEnergyService::characteristicChanged, this, &EqivaBluetooth::characteristicChanged);
|
||||
|
||||
// Debug
|
||||
qCDebug(dcEQ3()) << "Discovering service details";
|
||||
m_eqivaService->discoverDetails();
|
||||
|
||||
}
|
||||
|
||||
// Debug...
|
||||
void EqivaBluetooth::serviceStateChanged(QLowEnergyService::ServiceState newState)
|
||||
{
|
||||
qCDebug(dcEQ3()) << m_name << "Service state changed:" << newState;
|
||||
if (newState != QLowEnergyService::ServiceDiscovered) {
|
||||
return;
|
||||
}
|
||||
qCDebug(dcEQ3()) << m_name << "Service details discovered";
|
||||
|
||||
foreach (const QLowEnergyCharacteristic &characteristic, m_eqivaService->characteristics()) {
|
||||
qCDebug(dcEQ3()).nospace().noquote() << "C: --> " << characteristic.uuid().toString() << " (Handle 0x" << QString("%1").arg(characteristic.handle(), 0, 16) << " Name: " << characteristic.name() << "): " << characteristic.value().toHex() << characteristic.value();
|
||||
foreach (const QLowEnergyDescriptor &descriptor, characteristic.descriptors()) {
|
||||
qCDebug(dcEQ3()).nospace().noquote() << "D: --> " << descriptor.uuid().toString() << " (Handle 0x" << QString("%2").arg(descriptor.handle(), 0, 16) << " Name: " << descriptor.name() << "): " << descriptor.value().toHex() << characteristic.value();
|
||||
}
|
||||
// m_eqivaService->readCharacteristic(characteristic);
|
||||
}
|
||||
|
||||
m_available = true;
|
||||
m_reconnectAttempt = 0;
|
||||
emit availableChanged();
|
||||
|
||||
// // Debug...
|
||||
// foreach (const QLowEnergyCharacteristic &characteristic, m_eqivaService->characteristics()) {
|
||||
// qCDebug(dcEQ3()).nospace().noquote() << "C: --> " << characteristic.uuid().toString() << " (Handle 0x" << QString("%1").arg(characteristic.handle(), 0, 16) << " Name: " << characteristic.name() << "): " << characteristic.value().toHex() << characteristic.value();
|
||||
// foreach (const QLowEnergyDescriptor &descriptor, characteristic.descriptors()) {
|
||||
// qCDebug(dcEQ3()).nospace().noquote() << "D: --> " << descriptor.uuid().toString() << " (Handle 0x" << QString("%2").arg(descriptor.handle(), 0, 16) << " Name: " << descriptor.name() << "): " << descriptor.value().toHex() << characteristic.value();
|
||||
// }
|
||||
// }
|
||||
|
||||
sendDate();
|
||||
|
||||
// Enable notifications
|
||||
QLowEnergyCharacteristic characteristic = m_eqivaService->characteristic(notificationCharacteristicUuid);
|
||||
QLowEnergyDescriptor notificationDescriptor = characteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
||||
m_eqivaService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0000"));
|
||||
m_eqivaService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
|
||||
|
||||
}
|
||||
|
||||
void EqivaBluetooth::characteristicChanged(const QLowEnergyCharacteristic &info, const QByteArray &value)
|
||||
{
|
||||
qCDebug(dcEQ3()) << m_name << "Notification received" << info.uuid() << value.toHex();
|
||||
m_refreshTimer.start();
|
||||
|
||||
QByteArray data(value);
|
||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||
quint8 header;
|
||||
@ -254,7 +352,6 @@ void EqivaBluetooth::characteristicChanged(const QLowEnergyCharacteristic &info,
|
||||
if (header == notifyHeader) {
|
||||
quint8 notificationType;
|
||||
stream >> notificationType;
|
||||
|
||||
if (notificationType == notifyStatus) {
|
||||
quint8 lockAndMode;
|
||||
stream >> lockAndMode;
|
||||
@ -265,15 +362,17 @@ void EqivaBluetooth::characteristicChanged(const QLowEnergyCharacteristic &info,
|
||||
stream >> rawTemp;
|
||||
|
||||
quint8 lock = (lockAndMode & 0xF0);
|
||||
m_locked = (lock == keyLockOn) || (lock == windowAndKeyOn);
|
||||
m_windowOpen = (lock == windowLockOn) || (lock == windowAndKeyOn);
|
||||
m_locked = (lock & keyLockOn);
|
||||
m_windowOpen = (lock & windowLockOn);
|
||||
m_batteryCritical = (lock & batteryCriticalOn);
|
||||
|
||||
quint8 mode = (lockAndMode & 0x0F);
|
||||
m_targetTemp = 1.0 * rawTemp / 2;
|
||||
m_enabled = m_targetTemp >= 5;
|
||||
if (m_targetTemp < 5) {
|
||||
m_targetTemp = 5;
|
||||
}
|
||||
qCDebug(dcEQ3()) << m_name << "Status notification received: Enabled:" << m_enabled << "Temp:" << m_targetTemp << "Keylock:" << m_locked << "Window open:" << m_windowOpen << "Mode:" << mode << "Valve open:" << m_valveOpen << "Boost:" << m_boostEnabled;
|
||||
qCDebug(dcEQ3()) << m_name << "Status notification received: Enabled:" << m_enabled << "Temp:" << m_targetTemp << "Keylock:" << m_locked << "Window open:" << m_windowOpen << "Mode:" << mode << "Valve open:" << m_valveOpen << "Boost:" << m_boostEnabled << "Battery critical" << m_batteryCritical;
|
||||
|
||||
m_boostEnabled = false;
|
||||
switch (mode) {
|
||||
@ -307,6 +406,7 @@ void EqivaBluetooth::characteristicChanged(const QLowEnergyCharacteristic &info,
|
||||
emit windowOpenChanged();
|
||||
emit targetTemperatureChanged();
|
||||
emit valveOpenChanged();
|
||||
emit batteryCriticalChanged();
|
||||
|
||||
m_refreshTimer.start();
|
||||
} else if (notificationType == notifyProfile) {
|
||||
@ -344,6 +444,7 @@ void EqivaBluetooth::sendDate()
|
||||
stream << static_cast<quint8>(now.time().second());
|
||||
|
||||
// Example: 03130117172315 -> 03YYMMDDHHMMSS
|
||||
qCDebug(dcEQ3()) << "Updating date on device...";
|
||||
enqueue("SetDate", data);
|
||||
}
|
||||
|
||||
@ -422,9 +523,8 @@ void EqivaBluetoothDiscovery::deviceDiscoveryDone()
|
||||
|
||||
QStringList results;
|
||||
|
||||
qCDebug(dcEQ3()) << "Discovery finished";
|
||||
foreach (const QBluetoothDeviceInfo &deviceInfo, reply->discoveredDevices()) {
|
||||
qCDebug(dcEQ3()) << "Discovered device" << deviceInfo.name();
|
||||
qCDebug(dcEQ3()) << "Discovered Bluetooth device" << deviceInfo.name() << deviceInfo.address().toString();
|
||||
if (deviceInfo.name().contains("CC-RT-BLE")) {
|
||||
results.append(deviceInfo.address().toString());
|
||||
}
|
||||
|
||||
@ -40,6 +40,8 @@ public:
|
||||
|
||||
quint8 valveOpen() const;
|
||||
|
||||
bool batteryCritical() const;
|
||||
|
||||
signals:
|
||||
void availableChanged();
|
||||
void enabledChanged();
|
||||
@ -49,6 +51,7 @@ signals:
|
||||
void windowOpenChanged();
|
||||
void targetTemperatureChanged();
|
||||
void valveOpenChanged();
|
||||
void batteryCriticalChanged();
|
||||
|
||||
void commandResult(int id, bool result);
|
||||
|
||||
@ -82,6 +85,7 @@ private:
|
||||
Mode m_mode = ModeAuto;
|
||||
bool m_windowOpen = false;
|
||||
quint8 m_valveOpen = 0;
|
||||
bool m_batteryCritical = false;
|
||||
|
||||
int m_reconnectAttempt = 0;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user