// SPDX-License-Identifier: GPL-3.0-or-later /* * Qt mutizone MQTT thermostat * * Copyright (C) 2019 Richard Genoud * */ #include #include #include #include #include "settings.h" const char default_room_names[MAX_NB_ZONES][42] = { "Bedroom", "Living Room", "Workspace", "Bathroom" }; const char default_sensors_topics[MAX_NB_ZONES][64] = { "sensors/bedroom/xiaomi", "sensors/living_room/xiaomi", "sensors/workspace/xiaomi", "sensors/bathroom/xiaomi" }; const char default_availability_topics[MAX_NB_ZONES][64] = { "sensors/bedroom/availability", "sensors/living_room/availability", "sensors/workspace/availability", "sensors/bathroom/availability" }; const char default_control_topics[MAX_NB_ZONES][64] = { "heaters/bedroom", "heaters/living_room", "heaters/workspace", "heaters/bathroom" }; Settings *Settings::_singleton = NULL; Settings::Settings(QObject *parent) : QSettings(parent) { struct Room room; struct Heater heater; struct Program program; int nb_rooms; m_state = OFF; QString st = this->value("state", "off").toString(); if (st.compare(QString("on"), Qt::CaseInsensitive) == 0) { m_state = ON; } if (st.compare(QString("auto"), Qt::CaseInsensitive) == 0) { m_state = AUTO; } m_end_holiday = QDateTime::fromString(this->value("end_holiday", "2020-01-01T00:00:00Z").toString(), Qt::ISODate); if (!m_end_holiday.isValid()) { m_end_holiday = QDateTime::currentDateTime(); } nb_rooms = this->beginReadArray("rooms"); if (nb_rooms == 0) { this->endArray(); set_rooms_default_config(); nb_rooms = this->beginReadArray("rooms"); } if (nb_rooms > MAX_NB_ZONES) { // TODO; nb_rooms = MAX_NB_ZONES; } // TODO: handle unset values in a better way for (int i = 0; i < nb_rooms; ++i) { this->setArrayIndex(i); room.name = this->value("name", default_room_names[i]).toString(); room.sensor_topic = this->value("sensor_topic", default_sensors_topics[i]).toString(); room.availability_topic = this->value("availability_topic", default_availability_topics[i]).toString(); int size = this->beginReadArray("heaters"); for (int j = 0; j < size; ++j) { this->setArrayIndex(j); heater.ctrl_topic = this->value("control_topic", "").toString(); room.heaters << heater; } this->endArray(); room.default_temperature = this->value("default_temperature", 20).toDouble(); size = this->beginReadArray("temperature_schedule"); for (int j = 0; j < size; ++j) { /* TODO: check for overlapping schedules ? */ this->setArrayIndex(j); program.temperature = this->value("temperature", 20).toDouble(); program.DoW = this->value("days_of_week", 127).toInt(); program.start_time = QTime::fromString(this->value("start_time", "").toString(), "H:m"); program.end_time = QTime::fromString(this->value("end_time", "").toString(), "H:m"); if (program.start_time.isValid() && program.end_time.isValid() && (program.DoW > 0) && (program.DoW < 128)) { room.progs << program; } } this->endArray(); m_rooms << room; room.progs.clear(); room.heaters.clear(); } this->endArray(); m_broker.address = this->value("broker/address", "localhost").toString(); m_broker.port = this->value("broker/port", 1883).toInt(); } void Settings::setRoomDefaultTemperature(int idx, double temperature) { if ((idx < 0) || (idx >= MAX_NB_ZONES)) { // ERROR return; } this->beginWriteArray("rooms", nbZones()); this->setArrayIndex(idx); this->setValue("default_temperature", temperature); this->endArray(); this->sync(); } void Settings::setRoomPrograms(int idx, QVector &progs) { if ((idx < 0) || (idx >= MAX_NB_ZONES)) { // ERROR return; } this->beginWriteArray("rooms", nbZones()); this->setArrayIndex(idx); this->remove("temperature_schedule"); this->beginWriteArray("temperature_schedule"); for (int i = 0; i < progs.count(); i++) { this->setArrayIndex(i); this->setValue("temperature", progs.at(i).temperature); this->setValue("days_of_week", progs.at(i).DoW); this->setValue("start_time", progs.at(i).start_time.toString("H:m")); this->setValue("end_time", progs.at(i).end_time.toString("H:m")); } this->endArray(); this->endArray(); this->sync(); } void Settings::setPowerState(enum power_states state) { switch (state) { case OFF: m_state = OFF; this->setValue("state", "off"); break; case ON: m_state = ON; this->setValue("state", "on"); break; case AUTO: m_state = AUTO; this->setValue("state", "auto"); break; default: /* TODO: error */ break; } } void Settings::setEndHoliday(const QDateTime &endDate) { if (endDate.isValid()) { m_end_holiday = endDate; this->setValue("end_holiday", m_end_holiday.toString(Qt::ISODate)); } /* else TODO: error */ } void Settings::set_rooms_default_config(void) { this->setValue("state", "auto"); this->beginWriteArray("rooms"); for (int i = 0; i < MAX_NB_ZONES; i++) { this->setArrayIndex(i); this->setValue("name", tr(default_room_names[i])); this->setValue("sensor_topic", default_sensors_topics[i]); this->setValue("availability_topic", default_availability_topics[i]); this->setValue("default_temperature", 20); this->beginWriteArray("heaters"); this->setArrayIndex(0); this->setValue("control_topic", default_control_topics[i]); this->endArray(); } this->setArrayIndex(0); this->beginWriteArray("temperature_schedule"); this->setArrayIndex(0); this->setValue("temperature", 18); this->setValue("days_of_week", 127); this->setValue("start_time", QTime(22,0).toString("H:m")); this->setValue("end_time", QTime(7,0).toString("H:m")); this->endArray(); this->setArrayIndex(3); this->beginWriteArray("temperature_schedule"); this->setArrayIndex(0); this->setValue("temperature", FORCE_ON); this->setValue("days_of_week", 31); this->setValue("start_time", QTime(6,30).toString("H:m")); this->setValue("end_time", QTime(7,0).toString("H:m")); this->setArrayIndex(1); this->setValue("temperature", FORCE_ON); this->setValue("days_of_week", 96); this->setValue("start_time", QTime(7,30).toString("H:m")); this->setValue("end_time", QTime(8,0).toString("H:m")); this->endArray(); this->endArray(); this->sync(); } int Settings::nbZones(void) { return m_rooms.size(); } Settings::~Settings(void) { } Settings *Settings::getInstance(void) { if (!_singleton) { _singleton = new Settings(); } return _singleton; } /* vim: set tabstop=8 shiftwidth=8 softtabstop=0 noexpandtab: */