Skip to content
Snippets Groups Projects
heatControl.cpp 9.99 KiB
Newer Older
  • Learn to ignore specific revisions
  • Peter Altenbernd's avatar
    Peter Altenbernd committed
    #include <QTimer>
    #include <QFile>
    #include <sstream>
    #include <cassert>
    
    #include "heatControl.h"
    
    HeatControl * HeatControl::C[SHNodeIdSize * SHSensorIdSize] = {nullptr};
    QFile HeatControl::m_file("SHcontrol.csv");
    //    QDir::setCurrent("/tmp");
    
    
    /*
     *
     */
    HeatControl::HeatControl(SHsensor *temp, SHactuator *swtch, float maxTempDay, float maxTempNight, QTime startTimeDay, QTime startTimeNight, QObject *parent) :
        QObject(parent),
        m_temp(temp), m_switch(swtch),
        m_maxTempDay(maxTempDay), m_maxTempNight(maxTempNight),
        m_startTimeDay(startTimeDay), m_startTimeNight(startTimeNight)
    {
        m_mode = Mode::Auto; // default is Auto
    
        // Hinzufügen:
        m_pos = m_switch->pos();
    
        // qDebug() << m_name << pos;
    
        if (C[m_pos] != nullptr)
            throw std::invalid_argument("HeatControl::HeatControl: double usage");
    
        C[m_pos] = this;
    
        m_suspended = Suspension::NONE;
    }
    
    
    
    /*
     *
     */
    HeatControl::~HeatControl()
    {
        C[m_pos] = nullptr;
    }
    
    
    
    /*
     *
     */
    HeatControl::Mode HeatControl::mode() const
    {
        return m_mode;
    }
    
    
    
    
    /*
     *
     */
    QString HeatControl::value() const
    {
        return modeName(m_mode);
    }
    
    
    
    
    /*
     *
     */
    SHactuator::State HeatControl::state() const
    {
        return m_switch->switchState();
    
    }
    
    
    
    /*
     *
     */
    unsigned int HeatControl::demand() const
    {
        return m_switch->powerDemand();
    }
    
    
    /*
     *
     */
    float HeatControl::temperature() const
    {
        return m_temp->value().toFloat();
    }
    
    
    /*
     *
     */
    float HeatControl::maxTempDay() const
    {
        return m_maxTempDay;
    }
    
    
    /*
     *
     */
    float HeatControl::maxTempNight() const
    {
        return m_maxTempNight;
    }
    
    
    
    /*
     *
     */
    float HeatControl::minTemp() const
    {
        QTime now = SHsensor::currentTime();
    
        if (m_startTimeDay <= now and now < m_startTimeNight) // Tag
            return m_maxTempDay - autoTempMargin;
        else
            return m_maxTempNight;
    
    }
    
    
    /*
     *
     */
    QString HeatControl::name() const
    {
        return m_switch->name();
    }
    
    
    /*
     *
     */
    void HeatControl::grant(bool ON)
    {
        if (ON)
            m_switch->ON();
        else
            m_switch->OFF();
    }
    
    
    
    
    /*
     *
     */
    void HeatControl::suspend(bool maxTemp)
    {
        if (maxTemp)
            m_suspended = Suspension::MaxTemp;
        else
            if (m_suspended != Suspension::MaxTemp) // nicht überschreiben
                m_suspended = Suspension::MinTemp;
    
        QTime now = SHsensor::currentTime();
    
        QTime newExpireTime = SHsensor::currentTime().addSecs(60*suspensionTime);
    
        if (now < m_startTimeDay and newExpireTime > m_startTimeDay) // es ist noch Nacht, aber potenzielle expireTime liegt im Tag
            m_expireTime = m_startTimeDay; // => Setze expireTime auf Tagesbeginn
        else
            m_expireTime = newExpireTime;
    
        // qDebug() << "set" << name() << m_expireTime;
    }
    
    
    
    
    
    /*
     *
     */
    void HeatControl::checkSusExpiration()
    {
        QTime now = SHsensor::currentTime();
    
        // qDebug() << "HeatControl::checkSuspension before =>" << m_suspended;
        // qDebug() << "check" << name() << m_expireTime << now;
    
        if (m_expireTime.hour() == 0 and now.hour() == 23)
            return; // wait until after midnight
    
        if (m_expireTime <= now)
            m_suspended = Suspension::NONE;
    
        // qDebug() << "HeatControl::checkSuspension after =>" << m_suspended;
    }
    
    
    
    
    /*
     *
     */
    void HeatControl::checkResetSus(bool couldBeMoore)
    {
        // qDebug() << "checkResetSus" << couldBeMoore;
    
        if (m_suspended == Suspension::MinTemp and couldBeMoore)
            m_suspended = Suspension::NONE;
    
        // qDebug() << (int) m_suspended;
    }
    
    
    
    /*
     *
     */
    bool HeatControl::suspended() const
    {
        return (m_suspended != Suspension::NONE);
    }
    
    
    
    
    /*
     *
     */
    QString HeatControl::susName() const
    {
        switch (m_suspended) {
        case Suspension::NONE:
    
            return "OFF"; // no suspension -> else-part in SolarControl::process()
    
    Peter Altenbernd's avatar
    Peter Altenbernd committed
        case Suspension::MaxTemp:
            return "MXT";
        case Suspension::MinTemp:
            return "MIT";
        }
    }
    
    
    
    /*
     *
     */
    void HeatControl::remoteOn(int pos /* , bool setOn */)
    {
        // qDebug() << "remoteMsg" << setOn;
    
    
        C[pos]->m_previousMode = C[pos]->m_mode;
        C[pos]->m_previousState = C[pos]->m_switch->switchState();
        C[pos]->m_mode = Mode::RemoteOn;
    
        C[pos]->m_switch->ON(); // d.h. nicht auf process() warten
    }
    
    
    
    
    /*
     *
     */
    void HeatControl::resumeMode(int pos)
    {
        C[pos]->m_mode = C[pos]->m_previousMode;
    
        C[pos]->m_switch->set(C[pos]->m_previousState); // d.h. nicht auf process() warten
    }
    
    
    
    /*
     *
     */
    void HeatControl::processTimed()
    {
        QTime now = SHsensor::currentTime();
    
        // qDebug() << "HeatControl::processTimed" << temperature() << m_maxTempNight << m_maxTempDay;
    
        if (m_startTimeDay <= now and now < m_startTimeNight) { // Tag
            if (m_suspended == Suspension::NONE and temperature() < m_maxTempDay)
                m_switch->ON();
            else {
                m_switch->OFF();
    
                if (temperature() >= m_maxTempDay)
                    suspend(true);
            }
        } else { // Nacht
            if (m_suspended == Suspension::NONE and temperature() < m_maxTempNight)
                m_switch->ON();
            else {
                m_switch->OFF();
    
                if (temperature() >= m_maxTempNight)
                    suspend(true);
            }
        }
    
        if (suspended())
            checkSusExpiration();
    
        // Debug:
    /*    if (m_switch->switchState() == SHactuator::State::ON)
            qDebug() << "ON";
        else if (m_switch->switchState() == SHactuator::State::UNKOWN)
            qDebug() << "err";
        else if (suspended())
            qDebug() << "SUS";
        else
            qDebug() << "OFF"; */
    }
    
    
    
    
    
    
    /*
     *
     */
    void HeatControl::process()
    {
        // qDebug() << "HeatControl::process" << m_switch->name();
    
        switch (m_mode) {
        case Mode::Off:
            m_switch->OFF();
            break;
        case Mode::Timed:
            processTimed();
            break;
        case Mode::On:
            m_switch->ON();
            break;
        case Mode::Auto: // nichts zu tun -> wird von SolarControl gehandhabt
        case Mode::Smart:
        case Mode::RemoteOn: // nur der Vollständigkeit halber
        case Mode::size:
            break;
        }
    
    }
    
    
    
    
    
    /*
     * static
     */
    void HeatControl::processALL()
    {
        for (auto c : C)
            if (c != nullptr)
                c->process();
    }
    
    static QString getToken(std::istringstream & ss, char delim = sep) {
        std::string token;
    
        std::getline(ss, token, delim);
    
        // qDebug() << "token <" << token.c_str() << ">";
    
        return token.c_str();
    }
    
    /*
     *
     */
    void HeatControl::readCSV()
    {
        if (m_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            while (not m_file.atEnd()) {
                QString line = m_file.readLine();
    
                qDebug() << line;
    
                std::string input = line.toStdString();
                std::istringstream ss(input);
    
                QString name = getToken(ss);
                int pos = getToken(ss).toInt();
    
                if (pos < 0 or pos > SHNodeIdSize * SHSensorIdSize) {
                    qDebug() << "pos out of range" << pos;
                    continue;
                }
    
                if (C[pos] == nullptr) {
                    qDebug() << "C[pos] == nullptr" << pos;
                    continue;
                }
    
                if (C[pos]->m_switch->name() != name) {
                    qDebug() << "C[pos]->m_switch->name() != name" << pos;
                    continue;
                }
    
                C[pos]->m_mode = HeatControl::toMode(getToken(ss));
                C[pos]->m_maxTempDay = getToken(ss).toFloat();
                C[pos]->m_maxTempNight = getToken(ss).toFloat();
                C[pos]->m_startTimeDay = QTime::fromString(getToken(ss));
                C[pos]->m_startTimeNight = QTime::fromString(getToken(ss, '\n'));
    
                qDebug() << name << pos << modeName(C[pos]->m_mode)
                         << C[pos]->m_maxTempDay << C[pos]->m_maxTempNight
                         << C[pos]->m_startTimeDay << C[pos]->m_startTimeNight;
            }
    
    
            m_file.close();
        } else { // erstmalig
            writeCSV();
        }
    }
    
    /*
     *
     */
    void HeatControl::writeCSV()
    {
    
        if (not m_file.open(QIODevice::WriteOnly | QIODevice::Text))
            return;
    
        QTextStream out(&m_file);
    
    
        for (auto c : C)
            if (c != nullptr) {
                out << c->m_switch->name() << sep;
                out << c->m_pos << sep;
                out << modeName(c->mode()) << sep;
                out << c->m_maxTempDay << sep;
                out << c->m_maxTempNight << sep;
                out << c->m_startTimeDay.toString("hh:mm") << sep;
                out << c->m_startTimeNight.toString("hh:mm") << "\n";
            }
    
        m_file.close();
    }
    
    
    
    /*
     *
     */
    void HeatControl::setMode(int pos, const Mode &mode)
    {
        assert(pos >= 0 and pos < SHNodeIdSize * SHSensorIdSize);
    
        C[pos]->m_mode = mode;
    
        writeCSV();
    }
    
    
    
    /*
     *
     */
    QString HeatControl::getValue(int nid, int sid)
    {
        int pos = SHsensor::hash(nid, sid);
    
        if (pos == -1 or C[pos] == nullptr)
            return modeName(Mode::size);
        else
            return C[pos]->value();
    
    }
    
    
    /*
     *
     */
    QString HeatControl::getName(int nid, int sid)
    {
        int pos = SHsensor::hash(nid, sid);
    
        if (pos == -1 or C[pos] == nullptr)
            return "ERRname";
        else
            return C[pos]->name();
    }
    
    /*
     *
     */
    void HeatControl::setStartTimeNight(int pos, const QTime &startTimeNight)
    {
        assert(pos >= 0 and pos < SHNodeIdSize * SHSensorIdSize);
    
        C[pos]->m_startTimeNight = startTimeNight;
    
        writeCSV();
    }
    
    
    /*
     *
     */
    void HeatControl::setStartTimeDay(int pos, const QTime &startTimeDay)
    {
        assert(pos >= 0 and pos < SHNodeIdSize * SHSensorIdSize);
    
        C[pos]->m_startTimeDay = startTimeDay;
    
        writeCSV();
    }
    
    
    /*
     *
     */
    void HeatControl::setMaxTempNight(int pos, float maxTempNight)
    {
        assert(pos >= 0 and pos < SHNodeIdSize * SHSensorIdSize);
    
        C[pos]->m_maxTempNight = maxTempNight;
    
        writeCSV();
    }
    
    
    /*
     *
     */
    void HeatControl::setMaxTempDay(int pos, float maxTempDay)
    {
        assert(pos >= 0 and pos < SHNodeIdSize * SHSensorIdSize);
    
        C[pos]->m_maxTempDay = maxTempDay;
    
        writeCSV();
    }
    
    
    
    
    static QVector<QString> N = {"Off", "Auto", "Smart", "Timed", "On", "RemoteOn", "ERRnoMode"};
    
    /*
     *
     */
    QString HeatControl::modeName(HeatControl::Mode m)
    {
        return N[(int) m];
    }
    
    
    /*
     *
     */
    HeatControl::Mode HeatControl::toMode(const QString &m)
    {
        for (int i=0; i<N.size(); i++)
            if (N[i] == m)
                return (Mode) i;
    
        return HeatControl::Mode::Off; // default
    }