File indexing completed on 2024-04-28 03:43:41

0001 /*  Ekos Observatory Module
0002     SPDX-FileCopyrightText: Wolfgang Reissenberger <sterne-jaeger@t-online.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "observatoryweathermodel.h"
0008 #include "Options.h"
0009 #include <KLocalizedString>
0010 
0011 namespace Ekos
0012 {
0013 
0014 void ObservatoryWeatherModel::initModel(Weather *weather)
0015 {
0016     weatherInterface = weather;
0017 
0018     // ensure that we start the timers if required
0019     weatherChanged(status());
0020 
0021     connect(weatherInterface, &Weather::ready, this, [&]()
0022     {
0023         initialized = true;
0024         emit updateWeatherStatus();
0025     });
0026     connect(weatherInterface, &Weather::newStatus, this, &ObservatoryWeatherModel::weatherChanged);
0027     connect(weatherInterface, &Weather::newWeatherData, this, &ObservatoryWeatherModel::updateWeatherData);
0028     connect(weatherInterface, &Weather::newWeatherData, this, &ObservatoryWeatherModel::newWeatherData);
0029     connect(weatherInterface, &Weather::disconnected, this, [&]()
0030     {
0031         emit disconnected();
0032         initialized = false;
0033     });
0034 
0035     // read the default values
0036     warningActionsActive = Options::warningActionsActive();
0037     warningActions.parkDome = Options::weatherWarningCloseDome();
0038     warningActions.closeShutter = Options::weatherWarningCloseShutter();
0039     warningActions.delay = Options::weatherWarningDelay();
0040     alertActionsActive = Options::alertActionsActive();
0041     alertActions.parkDome = Options::weatherAlertCloseDome();
0042     alertActions.closeShutter = Options::weatherAlertCloseShutter();
0043     alertActions.delay = Options::weatherAlertDelay();
0044     m_autoScaleValues = Options::weatherAutoScaleValues();
0045 
0046     // not implemented yet
0047     warningActions.stopScheduler = false;
0048     alertActions.stopScheduler = false;
0049 
0050     warningTimer.setInterval(static_cast<int>(warningActions.delay * 1000));
0051     warningTimer.setSingleShot(true);
0052     alertTimer.setInterval(static_cast<int>(alertActions.delay * 1000));
0053     alertTimer.setSingleShot(true);
0054 
0055     connect(&warningTimer, &QTimer::timeout, [this]()
0056     {
0057         execute(warningActions);
0058     });
0059     connect(&alertTimer, &QTimer::timeout, [this]()
0060     {
0061         execute(alertActions);
0062     });
0063 
0064     if (weatherInterface->status() != ISD::Weather::WEATHER_IDLE)
0065         emit ready();
0066 
0067     initialized = true;
0068 }
0069 
0070 ISD::Weather::Status ObservatoryWeatherModel::status()
0071 {
0072     if (weatherInterface == nullptr)
0073         return ISD::Weather::WEATHER_IDLE;
0074 
0075     return weatherInterface->status();
0076 }
0077 
0078 bool ObservatoryWeatherModel::refresh()
0079 {
0080     return weatherInterface->refresh();
0081 }
0082 
0083 void ObservatoryWeatherModel::setWarningActionsActive(bool active)
0084 {
0085     warningActionsActive = active;
0086     Options::setWarningActionsActive(active);
0087 
0088     // stop warning actions if deactivated
0089     if (!active && warningTimer.isActive())
0090         warningTimer.stop();
0091     // start warning timer if activated
0092     else if (weatherInterface->status() == ISD::Weather::WEATHER_WARNING)
0093         startWarningTimer();
0094 }
0095 
0096 void ObservatoryWeatherModel::startWarningTimer()
0097 {
0098     if (warningActionsActive && (warningActions.parkDome || warningActions.closeShutter || warningActions.stopScheduler))
0099     {
0100         if (!warningTimer.isActive())
0101             warningTimer.start();
0102     }
0103     else if (warningTimer.isActive())
0104         warningTimer.stop();
0105 }
0106 
0107 void ObservatoryWeatherModel::setAlertActionsActive(bool active)
0108 {
0109     alertActionsActive = active;
0110     Options::setAlertActionsActive(active);
0111 
0112     // stop alert actions if deactivated
0113     if (!active && alertTimer.isActive())
0114         alertTimer.stop();
0115     // start alert timer if activated
0116     else if (weatherInterface->status() == ISD::Weather::WEATHER_ALERT)
0117         startAlertTimer();
0118 }
0119 
0120 void ObservatoryWeatherModel::setAutoScaleValues(bool value)
0121 {
0122     m_autoScaleValues = value;
0123     Options::setWeatherAutoScaleValues(value);
0124 }
0125 
0126 void ObservatoryWeatherModel::startAlertTimer()
0127 {
0128     if (alertActionsActive && (alertActions.parkDome || alertActions.closeShutter || alertActions.stopScheduler))
0129     {
0130         if (!alertTimer.isActive())
0131             alertTimer.start();
0132     }
0133     else if (alertTimer.isActive())
0134         alertTimer.stop();
0135 }
0136 
0137 void ObservatoryWeatherModel::setWarningActions(WeatherActions actions)
0138 {
0139     warningActions = actions;
0140     Options::setWeatherWarningCloseDome(actions.parkDome);
0141     Options::setWeatherWarningCloseShutter(actions.closeShutter);
0142     Options::setWeatherWarningDelay(actions.delay);
0143     if (!warningTimer.isActive())
0144         warningTimer.setInterval(static_cast<int>(actions.delay * 1000));
0145 
0146     if (weatherInterface->status() == ISD::Weather::WEATHER_WARNING)
0147         startWarningTimer();
0148 }
0149 
0150 
0151 QString ObservatoryWeatherModel::getWarningActionsStatus()
0152 {
0153     if (warningTimer.isActive())
0154     {
0155         int remaining = warningTimer.remainingTime() / 1000;
0156         return i18np("%1 second remaining", "%1 seconds remaining", remaining);
0157     }
0158 
0159     return i18n("Status: inactive");
0160 }
0161 
0162 void ObservatoryWeatherModel::setAlertActions(WeatherActions actions)
0163 {
0164     alertActions = actions;
0165     Options::setWeatherAlertCloseDome(actions.parkDome);
0166     Options::setWeatherAlertCloseShutter(actions.closeShutter);
0167     Options::setWeatherAlertDelay(actions.delay);
0168     if (!alertTimer.isActive())
0169         alertTimer.setInterval(static_cast<int>(actions.delay * 1000));
0170 
0171     if (weatherInterface->status() == ISD::Weather::WEATHER_ALERT)
0172         startAlertTimer();
0173 }
0174 
0175 QString ObservatoryWeatherModel::getAlertActionsStatus()
0176 {
0177     if (alertTimer.isActive())
0178     {
0179         int remaining = alertTimer.remainingTime() / 1000;
0180         return i18np("%1 second remaining", "%1 seconds remaining", remaining);
0181     }
0182 
0183     return i18n("Status: inactive");
0184 }
0185 
0186 void ObservatoryWeatherModel::updateWeatherStatus()
0187 {
0188     weatherChanged(status());
0189     emit ready();
0190 }
0191 
0192 
0193 void ObservatoryWeatherModel::weatherChanged(ISD::Weather::Status status)
0194 {
0195     switch (status)
0196     {
0197         case ISD::Weather::WEATHER_OK:
0198             warningTimer.stop();
0199             alertTimer.stop();
0200             break;
0201         case ISD::Weather::WEATHER_WARNING:
0202             alertTimer.stop();
0203             startWarningTimer();
0204             break;
0205         case ISD::Weather::WEATHER_ALERT:
0206             warningTimer.stop();
0207             startAlertTimer();
0208             break;
0209         default:
0210             break;
0211     }
0212     emit newStatus(status);
0213 }
0214 
0215 void ObservatoryWeatherModel::updateWeatherData(const std::vector<ISD::Weather::WeatherData> &data)
0216 {
0217     // add or update all received values
0218     for (auto &oneEntry : data)
0219     {
0220         // update if already existing
0221         unsigned long pos = findWeatherData(oneEntry.name);
0222         if (pos < m_WeatherData.size())
0223             m_WeatherData[pos].value = oneEntry.value;
0224         // new weather sensor?
0225         else if (oneEntry.name.startsWith("WEATHER_"))
0226             m_WeatherData.push_back({QString(oneEntry.name), QString(oneEntry.label), oneEntry.value});
0227     }
0228     // update UI
0229     emit newStatus(status());
0230 }
0231 
0232 unsigned long ObservatoryWeatherModel::findWeatherData(const QString name)
0233 {
0234     unsigned long i;
0235     for (i = 0; i < m_WeatherData.size(); i++)
0236     {
0237         if (m_WeatherData[i].name.compare(name) == 0)
0238             return i;
0239     }
0240     // none found
0241     return i;
0242 }
0243 } // Ekos