Browse Source

thermostat: implement BOOST function

master
Richard Genoud 4 years ago
parent
commit
da92b55a56
7 changed files with 208 additions and 5 deletions
  1. +48
    -0
      soft/thermostat/inc/boost_dlg.h
  2. +3
    -0
      soft/thermostat/inc/mainwindow.h
  3. +4
    -1
      soft/thermostat/inc/zoneitem.h
  4. +94
    -0
      soft/thermostat/src/boost_dlg.cpp
  5. +51
    -4
      soft/thermostat/src/mainwindow.cpp
  6. +6
    -0
      soft/thermostat/src/zoneitem.cpp
  7. +2
    -0
      soft/thermostat/thermostat.pro

+ 48
- 0
soft/thermostat/inc/boost_dlg.h View File

@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-3.0-or-later
/*
* Qt mutizone MQTT thermostat
*
* Copyright (C) 2020 Richard Genoud
*
*/
#ifndef BOOSTDLG_H
#define BOOSTDLG_H
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QDialog>
#include <QObject>
#include <QDateTime>
struct boost_data
{
double temperature;
QDateTime end_date;
};
class BoostDlg : public QDialog
{
Q_OBJECT
public:
BoostDlg(int idx, const QString &zoneName, double temperature = 21,
QWidget *parent = Q_NULLPTR,
Qt::WindowFlags f = Qt::WindowFlags());
~BoostDlg();
int m_idx; // room index
private:
QDoubleSpinBox m_boost_temperature;
QSpinBox m_boost_duration;
private slots:
void send_result(void);
signals:
void boost_changed(int idx, struct boost_data &data);
};
#endif // BOOSTDLG_H
/* vim: set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab: */

+ 3
- 0
soft/thermostat/inc/mainwindow.h View File

@ -16,6 +16,7 @@
#include "mqttclient.h"
#include "zoneitem.h"
#include "boost_dlg.h"
#include "settings.h"
class MainWindow : public QMainWindow
@ -42,6 +43,8 @@ private slots:
void availability_slot(int idx, bool ok);
void change_state(void);
void apply_order_to_heaters(void);
void show_boost(void);
void boost_slot(int idx, struct boost_data &data);
signals:
void setAllHeatersOn(bool on);


+ 4
- 1
soft/thermostat/inc/zoneitem.h View File

@ -14,6 +14,8 @@
#include <QLabel>
#include <QPushButton>
#include "boost_dlg.h"
class ZoneItem : public QWidget
{
Q_OBJECT
@ -28,8 +30,9 @@ public:
double m_target_temperature;
bool m_available;
bool m_heating_on;
QString m_name;
struct boost_data m_boost;
private:
QPushButton m_zoneNameBtn;
QPushButton m_temperatureBtn;
QPushButton m_hygroBtn;


+ 94
- 0
soft/thermostat/src/boost_dlg.cpp View File

@ -0,0 +1,94 @@
// SPDX-License-Identifier: GPL-3.0-or-later
/*
* Qt mutizone MQTT thermostat
*
* Copyright (C) 2020 Richard Genoud
*
*/
#include <QDialogButtonBox>
#include <QSpinBox>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLocale>
#include <QLabel>
#include <QtMath>
#include <QDateTime>
#include "settings.h"
#include "boost_dlg.h"
#define SPIN_ARROW_W 75
#define SPIN_ARROW_H 50
#define SPIN_FONT_SZ 20
BoostDlg::BoostDlg(int idx, const QString &zoneName, double temperature, QWidget *parent, Qt::WindowFlags f) :
QDialog(parent, f)
{
QString sheet;
QLabel *room_name = new QLabel(QString(tr("Force %1 temperature:").arg(zoneName)));
room_name->setStyleSheet(QString("font-size: %1px;").arg(SPIN_FONT_SZ));
temperature = qFloor(temperature * 2) / 2.0;
m_idx = idx;
m_boost_temperature.setDecimals(1);
m_boost_temperature.setValue(temperature);
m_boost_temperature.setSingleStep(0.5);
m_boost_temperature.setSuffix(" °C");
/*
* TODO: setting size in pixels sucks
* We should set size in mm or ratio of the window size
*/
sheet = QString("QDoubleSpinBox { height: %1px; font-size: %4px }"
"QDoubleSpinBox::up-button { width: %2px; height: %3px }"
"QDoubleSpinBox::down-button { width: %2px; height: %3px }")
.arg(2*SPIN_ARROW_H)
.arg(SPIN_ARROW_W)
.arg(SPIN_ARROW_H)
.arg(SPIN_FONT_SZ);
m_boost_temperature.setStyleSheet(sheet);
m_boost_duration.setRange(0, 99);
m_boost_duration.setValue(1);
m_boost_duration.setSuffix(" H");
sheet = sheet.replace("QDoubleSpinBox", "QSpinBox");
m_boost_duration.setStyleSheet(sheet);
QHBoxLayout *spinLayout = new QHBoxLayout;
spinLayout->addWidget(&m_boost_temperature);
spinLayout->addWidget(&m_boost_duration);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted(void)), this, SLOT(accept(void)));
connect(buttonBox, SIGNAL(rejected(void)), this, SLOT(reject(void)));
connect(this, SIGNAL(accepted(void)), this, SLOT(send_result(void)));
QVBoxLayout *topLayout = new QVBoxLayout;
topLayout->addWidget(room_name);
topLayout->addLayout(spinLayout);
topLayout->addWidget(buttonBox);
this->setLayout(topLayout);
}
void BoostDlg::send_result(void)
{
struct boost_data data;
QDateTime now = QDateTime::currentDateTime();
data.temperature = m_boost_temperature.value();
data.end_date = now.addSecs(m_boost_duration.value() * 3600);
emit boost_changed(m_idx, data);
}
BoostDlg::~BoostDlg()
{
}
/* vim: set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab: */

+ 51
- 4
soft/thermostat/src/mainwindow.cpp View File

@ -8,12 +8,14 @@
#include <QtWidgets>
#include <QPushButton>
#include <QDateTime>
#include <QTime>
#include <QDate>
#include <QtMath>
#include <QLocale>
#include <QVector>
#include "boost_dlg.h"
#include "mqttclient.h"
#include "zoneitem.h"
#include "settings.h"
@ -28,7 +30,9 @@ MainWindow::MainWindow(QWidget *parent) :
for (int i = 0; i < s->nbZones(); i++) {
zone = new ZoneItem(s->m_rooms.at(i).name, this);
zone->m_zoneNameBtn.setProperty("idx", i);
zone->m_target_temperature = get_target_temperature(i);
connect(&(zone->m_zoneNameBtn), SIGNAL(clicked()), this, SLOT(show_boost()));
m_zones << zone;
}
@ -93,6 +97,36 @@ MainWindow::~MainWindow()
{
}
void MainWindow::boost_slot(int idx, struct boost_data &data)
{
qDebug() << "room " << m_zones.at(idx)->m_name << " new BOOST " << data.temperature << " end: " << data.end_date;
m_zones.at(idx)->m_boost = data;
apply_order_to_heaters();
}
void MainWindow::show_boost(void)
{
QObject* obj = sender();
QVariant v;
v = obj->property("idx");
if (!v.isValid())
return;
int idx = v.toInt();
if ((idx < 0) || (idx >= MAX_NB_ZONES))
return;
BoostDlg boost(idx, m_zones.at(idx)->m_name, m_zones.at(idx)->m_target_temperature, this);
connect(&boost, SIGNAL(boost_changed(int, struct boost_data &)), this, SLOT(boost_slot(int, struct boost_data &)));
boost.showFullScreen();
boost.exec();
}
void MainWindow::update_state_btn(enum power_states st)
{
switch (st) {
@ -116,8 +150,9 @@ double MainWindow::get_target_temperature(int room_idx)
Settings *s = Settings::getInstance();
const struct Room *r = NULL;
const struct Program *p = NULL;
const struct boost_data *b = NULL;
double target = FORCE_OFF;
QTime now = QTime::currentTime();
QDateTime now = QDateTime::currentDateTime();
uint8_t dow = QDate::currentDate().dayOfWeek();
if ((room_idx < 0) || (room_idx >= MAX_NB_ZONES)) {
@ -131,6 +166,18 @@ double MainWindow::get_target_temperature(int room_idx)
}
/*
* Check if there's a boost programmation
*/
if (room_idx < m_zones.count()) {
b = &(m_zones.at(room_idx)->m_boost);
if (b->end_date.isValid() && (b->end_date > now)) {
/* BOOST is active */
target = b->temperature;
goto out;
}
}
/*
* dayOfWeek() returns 1 for monday, 7 for sunday.
* so dow -= 1 gives 0 for monday, 6 for sunday.
* And (1 << dow) gives the day of week as a bit field
@ -147,17 +194,17 @@ double MainWindow::get_target_temperature(int room_idx)
* Ex: from 10h to 18h
*/
if (p->start_time < p->end_time) {
if ((now >= p->start_time) && (now < p->end_time)) {
if ((now.time() >= p->start_time) && (now.time() < p->end_time)) {
target = p->temperature;
}
} else {
/*
* Ex: from 22h to 6h
*/
if (now >= p->start_time) {
if (now.time() >= p->start_time) {
target = p->temperature;
} else {
if (now < p->end_time) {
if (now.time() < p->end_time) {
target = p->temperature;
}
}


+ 6
- 0
soft/thermostat/src/zoneitem.cpp View File

@ -11,6 +11,8 @@
#include <QWidget>
#include <QLocale>
#include <QLabel>
#include <QDateTime>
#include <QTime>
#include "settings.h"
#include "zoneitem.h"
@ -18,6 +20,7 @@
ZoneItem::ZoneItem(const QString &zoneName, QWidget *parent) :
QWidget(parent)
{
m_name = zoneName;
m_zoneNameBtn.setText(zoneName);
m_zoneNameBtn.setFlat(true);
m_temperatureBtn.setFlat(true);
@ -28,6 +31,9 @@ ZoneItem::ZoneItem(const QString &zoneName, QWidget *parent) :
m_target_temperature = FORCE_OFF;
m_available = false;
m_boost.temperature = 0;
m_boost.end_date = QDateTime();
/*
* Layout for the left part of the window
*/


+ 2
- 0
soft/thermostat/thermostat.pro View File

@ -25,12 +25,14 @@ SOURCES += src/main.cpp \
src/zoneitem.cpp \
src/mqttclient.cpp \
src/settings.cpp \
src/boost_dlg.cpp \
HEADERS += inc/mainwindow.h \
inc/zoneitem.h \
inc/mqttclient.h \
inc/settings.h \
inc/boost_dlg.h \
RESOURCES += thermostat.qrc


Loading…
Cancel
Save