diff --git a/plugins/deviceplugins/datetime/alarm.cpp b/plugins/deviceplugins/datetime/alarm.cpp new file mode 100644 index 00000000..ba2ebe71 --- /dev/null +++ b/plugins/deviceplugins/datetime/alarm.cpp @@ -0,0 +1,302 @@ +#include "alarm.h" +#include "loggingcategories.h" + +Alarm::Alarm(QObject *parent) : + QObject(parent) +{ +} + +void Alarm::setName(const QString &name) +{ + m_name = name; +} + +QString Alarm::name() const +{ + return m_name; +} + +void Alarm::setMonday(const bool &monday) +{ + m_monday = monday; +} + +bool Alarm::monday() const +{ + return m_monday; +} + +void Alarm::setTuesday(const bool &tuesday) +{ + m_tuesday = tuesday; +} + +bool Alarm::tuesday() const +{ + return m_tuesday; +} + +void Alarm::setWednesday(const bool &wednesday) +{ + m_wednsday = wednesday; +} + +bool Alarm::wednesday() const +{ + return m_wednsday; +} + +void Alarm::setThursday(const bool &thursday) +{ + m_thursday = thursday; +} + +bool Alarm::thursday() const +{ + return m_thursday; +} + +void Alarm::setFriday(const bool &friday) +{ + m_friday = friday; +} + +bool Alarm::friday() const +{ + return m_friday; +} + +void Alarm::setSaturday(const bool &saturday) +{ + m_saturday = saturday; +} + +bool Alarm::saturday() const +{ + return m_saturday; +} + +void Alarm::setSunday(const bool &sunday) +{ + m_sunday = sunday; +} + +bool Alarm::sunday() const +{ + return m_sunday; +} + +void Alarm::setMinutes(const int &minutes) +{ + m_minutes = minutes; +} + +int Alarm::minutes() const +{ + return m_minutes; +} + +void Alarm::setHours(const int &hours) +{ + m_hours = hours; +} + +int Alarm::hours() const +{ + return m_hours; +} + +void Alarm::setOffset(const int &offset) +{ + m_offset = offset; +} + +int Alarm::offset() const +{ + return m_offset; +} + +void Alarm::setDusk(const QDateTime &dusk) +{ + m_duskOffset = calculateOffsetTime(dusk); +} + +void Alarm::setSunrise(const QDateTime &sunrise) +{ + m_sunriseOffset = calculateOffsetTime(sunrise); +} + +void Alarm::setNoon(const QDateTime &noon) +{ + m_noonOffset = calculateOffsetTime(noon); +} + +void Alarm::setDawn(const QDateTime &dawn) +{ + m_dawnOffset = calculateOffsetTime(dawn); +} + +void Alarm::setSunset(const QDateTime &sunset) +{ + m_sunsetOffset = calculateOffsetTime(sunset); +} + +void Alarm::setTimeType(const Alarm::TimeType &timeType) +{ + m_timeType = timeType; +} + +void Alarm::setTimeType(const QString &timeType) +{ + if (timeType == "time") { + m_timeType = TimeTypeTime; + } else if (timeType == "dusk") { + m_timeType = TimeTypeDusk; + } else if (timeType == "sunrise") { + m_timeType = TimeTypeSunrise; + } else if (timeType == "noon") { + m_timeType = TimeTypeNoon; + } else if (timeType == "dawn") { + m_timeType = TimeTypeDawn; + } else if (timeType == "sunset") { + m_timeType = TimeTypeSunset; + } +} + +Alarm::TimeType Alarm::timeType() const +{ + return m_timeType; +} + +QDateTime Alarm::calculateOffsetTime(const QDateTime &dateTime) const +{ + QDateTime offsetTime = QDateTime(dateTime); + offsetTime.time().addSecs(m_offset * 60); + return offsetTime; +} + +bool Alarm::checkDayOfWeek(const QDateTime &dateTime) +{ + QDateTime offsetTime = calculateOffsetTime(dateTime); + + switch (offsetTime.date().dayOfWeek()) { + case Qt::Monday: + return monday(); + break; + case Qt::Tuesday: + return tuesday(); + break; + case Qt::Wednesday: + return wednesday(); + break; + case Qt::Thursday: + return thursday(); + break; + case Qt::Friday: + return friday(); + break; + case Qt::Saturday: + return saturday(); + break; + case Qt::Sunday: + return sunday(); + break; + default: + return false; + } +} + +bool Alarm::checkHour(const QDateTime &dateTime) +{ + QDateTime offsetTime = calculateOffsetTime(dateTime); + + if (offsetTime.time().hour() != m_hours) { + return false; + } + return true; +} + +bool Alarm::checkMinute(const QDateTime &dateTime) +{ + QDateTime offsetTime = calculateOffsetTime(dateTime); + + if (offsetTime.time().minute() != m_minutes) { + return false; + } + return true; +} + +bool Alarm::checkTimeTypes(const QDateTime &dateTime) +{ + bool checkOk = false; + switch (m_timeType) { + case TimeTypeTime: + qCWarning(dcDateTime) << name() << "wrong time type"; + checkOk = false; + break; + case TimeTypeDusk: + if (m_duskOffset == dateTime) { + qCDebug(dcDateTime) << name() << "match dusk with offset" << m_offset; + checkOk = true; + } + break; + case TimeTypeSunrise: + if (m_sunriseOffset == dateTime) { + qCDebug(dcDateTime) << name() << "match sunrise with offset" << m_offset; + checkOk = true; + } + break; + case TimeTypeNoon: + if (m_noonOffset == dateTime) { + qCDebug(dcDateTime) << name() << "match noon with offset" << m_offset; + checkOk = true; + } + break; + case TimeTypeDawn: + if (m_dawnOffset == dateTime) { + qCDebug(dcDateTime) << name() << "match dawn with offset" << m_offset; + checkOk = true; + } + break; + case TimeTypeSunset: + if (m_sunsetOffset == dateTime) { + qCDebug(dcDateTime) << name() << "match sunset with offset" << m_offset; + checkOk = true; + } + break; + default: + checkOk = false; + } + return checkOk; +} + +void Alarm::validate(const QDateTime &dateTime) +{ + qCDebug(dcDateTime) << name() << "validate" << dateTime.toString() << "..."; + + if (!checkDayOfWeek(dateTime)) + return; + + // check if should use the given time + if (m_timeType == TimeTypeTime) { + if (!checkHour(dateTime)) + return; + + if (!checkMinute(dateTime)) + return; + + qCDebug(dcDateTime) << name() << "match time" << QTime(hours(), minutes()).toString("hh:mm") << "with offset" << m_offset; + emit alarm(); + } +} + +void Alarm::validateTimes(const QDateTime &dateTime) +{ + if (m_timeType == TimeTypeTime) + return; + + if (!checkTimeTypes(dateTime)) + return; + + emit alarm(); +} diff --git a/plugins/deviceplugins/datetime/alarm.h b/plugins/deviceplugins/datetime/alarm.h new file mode 100644 index 00000000..8c7b12c5 --- /dev/null +++ b/plugins/deviceplugins/datetime/alarm.h @@ -0,0 +1,103 @@ +#ifndef ALARM_H +#define ALARM_H + +#include +#include + +class Alarm : public QObject +{ + Q_OBJECT +public: + enum TimeType { + TimeTypeTime, + TimeTypeDusk, + TimeTypeSunrise, + TimeTypeNoon, + TimeTypeSunset, + TimeTypeDawn + }; + + explicit Alarm(QObject *parent = 0); + + void setName(const QString &name); + QString name() const; + + void setMonday(const bool &monday); + bool monday() const; + + void setTuesday(const bool &tuesday); + bool tuesday() const; + + void setWednesday(const bool &wednesday); + bool wednesday() const; + + void setThursday(const bool &thursday); + bool thursday() const; + + void setFriday(const bool &friday); + bool friday() const; + + void setSaturday(const bool &saturday); + bool saturday() const; + + void setSunday(const bool &sunday); + bool sunday() const; + + void setMinutes(const int &minutes); + int minutes() const; + + void setHours(const int &hours); + int hours() const; + + void setOffset(const int &offset); + int offset() const; + + void setDusk(const QDateTime &dusk); + void setSunrise(const QDateTime &sunrise); + void setNoon(const QDateTime &noon); + void setDawn(const QDateTime &dawn); + void setSunset(const QDateTime &sunset); + + void setTimeType(const TimeType &timeType); + void setTimeType(const QString &timeType); + TimeType timeType() const; + +private: + QString m_name; + bool m_monday; + bool m_tuesday; + bool m_wednsday; + bool m_thursday; + bool m_friday; + bool m_saturday; + bool m_sunday; + + int m_minutes; + int m_hours; + int m_offset; + TimeType m_timeType; + + QDateTime m_duskOffset; + QDateTime m_sunriseOffset; + QDateTime m_noonOffset; + QDateTime m_sunsetOffset; + QDateTime m_dawnOffset; + + QDateTime calculateOffsetTime(const QDateTime &dateTime) const; + + bool checkDayOfWeek(const QDateTime &dateTime); + bool checkHour(const QDateTime &dateTime); + bool checkMinute(const QDateTime &dateTime); + + bool checkTimeTypes(const QDateTime &dateTime); + +signals: + void alarm(); + +public slots: + void validate(const QDateTime &dateTime); + void validateTimes(const QDateTime &dateTime); + +}; + +#endif // ALARM_H diff --git a/plugins/deviceplugins/datetime/datetime.pro b/plugins/deviceplugins/datetime/datetime.pro index 0ed7f8a1..e36fccca 100644 --- a/plugins/deviceplugins/datetime/datetime.pro +++ b/plugins/deviceplugins/datetime/datetime.pro @@ -3,8 +3,10 @@ include (../../plugins.pri) TARGET = $$qtLibraryTarget(guh_deviceplugindatetime) SOURCES += \ - deviceplugindatetime.cpp + deviceplugindatetime.cpp \ + alarm.cpp HEADERS += \ - deviceplugindatetime.h + deviceplugindatetime.h \ + alarm.h diff --git a/plugins/deviceplugins/datetime/deviceplugindatetime.cpp b/plugins/deviceplugins/datetime/deviceplugindatetime.cpp index a630eb2a..f28cda91 100644 --- a/plugins/deviceplugins/datetime/deviceplugindatetime.cpp +++ b/plugins/deviceplugins/datetime/deviceplugindatetime.cpp @@ -84,106 +84,365 @@ #include "plugininfo.h" #include "loggingcategories.h" -DevicePluginDateTime::DevicePluginDateTime() +#include +#include + +DevicePluginDateTime::DevicePluginDateTime() : + m_timer(0), + m_todayDevice(0), + m_timeZone(QTimeZone("Europe/Vienna")) { m_timer = new QTimer(this); m_timer->setInterval(1000); - qCDebug(dcDateTime) << configuration(); - m_timeZone = QTimeZone(configValue("timezone").toByteArray()); + m_currentDateTime = QDateTime(QDate::currentDate(), QTime::currentTime(), m_timeZone); - connect(m_timer, &QTimer::timeout, this, &DevicePluginDateTime::timeout); + connect(m_timer, &QTimer::timeout, this, &DevicePluginDateTime::onTimeout); + connect(this, &DevicePluginDateTime::minuteChanged, this, &DevicePluginDateTime::onMinuteChanged); + connect(this, &DevicePluginDateTime::hourChanged, this, &DevicePluginDateTime::onHourChanged); + connect(this, &DevicePluginDateTime::dayChanged, this, &DevicePluginDateTime::onDayChanged); + connect(this, &DevicePluginDateTime::timeDataChanged, this, &DevicePluginDateTime::onTimeDataUpdate); connect(this, &DevicePluginDateTime::configValueChanged, this, &DevicePluginDateTime::onConfigValueChanged); } DeviceManager::HardwareResources DevicePluginDateTime::requiredHardware() const { - return DeviceManager::HardwareResourceNone; + return DeviceManager::HardwareResourceNetworkManager; } QList DevicePluginDateTime::configurationDescription() const { QList params; ParamType timezoneParamType("timezone", QVariant::String, "Europe/Vienna"); + QList allowedValues; foreach (QByteArray timeZone, QTimeZone::availableTimeZoneIds()) { allowedValues.append(timeZone); } timezoneParamType.setAllowedValues(allowedValues); + params.append(timezoneParamType); return params; } DeviceManager::DeviceSetupStatus DevicePluginDateTime::setupDevice(Device *device) { - // check the DeviceClassId - - device->setName("Time (" + device->paramValue("timezone").toString() + ")"); - m_timeZone = QTimeZone(device->paramValue("timezone").toByteArray()); - - if(m_timeZone.isValid()){ - QDateTime zoneTime = QDateTime(QDate::currentDate(), QTime::currentTime(), m_timeZone).toLocalTime(); - qCDebug(dcDateTime) << zoneTime.toLocalTime().date() << zoneTime.toLocalTime().time() << QLocale::countryToString(m_timeZone.country()); - m_timer->start(); - - return DeviceManager::DeviceSetupStatusSuccess; + // check timezone + if(!m_timeZone.isValid()){ + qCWarning(dcDateTime) << "invalid time zone."; + return DeviceManager::DeviceSetupStatusFailure; } - return DeviceManager::DeviceSetupStatusFailure; + + // date + if (device->deviceClassId() == todayDeviceClassId) { + if (m_todayDevice != 0) { + qCWarning(dcDateTime) << "there is already a date device or not deleted correctly! this should never happen!!"; + return DeviceManager::DeviceSetupStatusFailure; + } + m_todayDevice = device; + qCDebug(dcDateTime) << "create today device: current time" << m_currentDateTime.currentDateTime().toString(); + } + + // alarm + if (device->deviceClassId() == alarmDeviceClassId) { + Alarm *alarm = new Alarm(this); + alarm->setName(device->paramValue("name").toString()); + alarm->setMonday(device->paramValue("monday").toBool()); + alarm->setTuesday(device->paramValue("tuesday").toBool()); + alarm->setWednesday(device->paramValue("wednesday").toBool()); + alarm->setThursday(device->paramValue("thursday").toBool()); + alarm->setFriday(device->paramValue("friday").toBool()); + alarm->setSaturday(device->paramValue("saturday").toBool()); + alarm->setSunday(device->paramValue("sunday").toBool()); + alarm->setMinutes(device->paramValue("minutes").toInt()); + alarm->setHours(device->paramValue("hours").toInt()); + alarm->setTimeType(device->paramValue("time type").toString()); + alarm->setOffset(device->paramValue("offset").toInt()); + + connect(alarm, &Alarm::alarm, this, &DevicePluginDateTime::onAlarm); + + m_alarms.insert(device, alarm); + } + + m_timer->start(); + + return DeviceManager::DeviceSetupStatusSuccess; +} + +void DevicePluginDateTime::postSetupDevice(Device *device) +{ + Q_UNUSED(device) + qCDebug(dcDateTime) << "post setup"; + searchGeoLocation(); } void DevicePluginDateTime::deviceRemoved(Device *device) { - Q_UNUSED(device); - m_timer->stop(); + // check if we still need the timer + if (myDevices().count() == 0) { + m_timer->stop(); + } + + // date + if (device->deviceClassId() == todayDeviceClassId) { + m_todayDevice = 0; + } + + // alarm + if (device->deviceClassId() == alarmDeviceClassId) { + Alarm *alarm = m_alarms.take(device); + alarm->deleteLater(); + } + startMonitoringAutoDevices(); } -DeviceManager::DeviceError DevicePluginDateTime::executeAction(Device *device, const Action &action) +void DevicePluginDateTime::networkManagerReplyReady(QNetworkReply *reply) { - Q_UNUSED(device); - Q_UNUSED(action); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - return DeviceManager::DeviceErrorNoError; + if (m_locationReplies.contains(reply)) { + m_locationReplies.removeAll(reply); + if (status != 200) { + qCWarning(dcDateTime) << "http error status for location request:" << status << reply->error(); + } else { + processGeoLocationData(reply->readAll()); + } + } else if (m_timeReplies.contains(reply)) { + m_timeReplies.removeAll(reply); + if (status != 200) { + qCWarning(dcDateTime) << "http error status for time request:" << status << reply->error(); + } else { + processTimesData(reply->readAll()); + } + } + reply->deleteLater(); } void DevicePluginDateTime::startMonitoringAutoDevices() { foreach (Device *device, myDevices()) { - if (device->deviceClassId() == dateDeviceClassId) { - return; // We already have a Auto Mock device... do nothing. + if (device->deviceClassId() == todayDeviceClassId) { + return; // We already have the date device... do nothing. } } - DeviceDescriptor dateDescriptor(dateDeviceClassId, QString("Date"), QString(m_timeZone.id())); + DeviceDescriptor dateDescriptor(todayDeviceClassId, QString("Date"), QString(m_timeZone.id())); ParamList params; params.append(Param("name", m_timeZone.id())); dateDescriptor.setParams(params); - emit autoDevicesAppeared(dateDeviceClassId, QList() << dateDescriptor); + emit autoDevicesAppeared(todayDeviceClassId, QList() << dateDescriptor); } -void DevicePluginDateTime::timeout() +void DevicePluginDateTime::searchGeoLocation() +{ + if (m_todayDevice == 0) + return; + + QNetworkRequest request; + request.setUrl(QUrl("http://ip-api.com/json")); + + qCDebug(dcDateTime) << "request geo location."; + + QNetworkReply *reply = networkManagerGet(request); + m_locationReplies.append(reply); +} + +void DevicePluginDateTime::processGeoLocationData(const QByteArray &data) +{ + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + + if(error.error != QJsonParseError::NoError) { + qCWarning(dcDateTime) << "failed to parse location JSON data:" << error.errorString() << ":" << data ; + return; + } + + //qCDebug(dcDateTime) << "geo location data received:" << jsonDoc.toJson(); + QVariantMap response = jsonDoc.toVariant().toMap(); + if (response.value("status") != "success") { + qCWarning(dcDateTime) << "failed to request geo location:" << response.value("status"); + } + + // check timezone + QString timeZone = response.value("timezone").toString(); + if (QString(m_timeZone.id()) != timeZone) { + qCWarning(dcDateTime) << "error: configured timezone does not match the discovered timezone"; + qCWarning(dcDateTime) << " configured:" << m_timeZone.id(); + qCWarning(dcDateTime) << " discovered:" << timeZone; + return; + } + + qCDebug(dcDateTime) << "---------------------------------------------"; + qCDebug(dcDateTime) << "autodetected location for" << response.value("query").toString(); + qCDebug(dcDateTime) << " city :" << response.value("city").toString(); + qCDebug(dcDateTime) << " country :" << response.value("country").toString(); + qCDebug(dcDateTime) << " code :" << response.value("countryCode").toString(); + qCDebug(dcDateTime) << " zip code :" << response.value("zip").toString(); + qCDebug(dcDateTime) << " lon :" << response.value("lon").toByteArray(); + qCDebug(dcDateTime) << " lat :" << response.value("lat").toByteArray(); + qCDebug(dcDateTime) << "---------------------------------------------"; + + getTimes(response.value("lat").toString(), response.value("lon").toString()); +} + +void DevicePluginDateTime::getTimes(const QString &latitude, const QString &longitude) +{ + QUrlQuery urlQuery; + urlQuery.addQueryItem("lat", latitude); + urlQuery.addQueryItem("lng", longitude); + urlQuery.addQueryItem("date", "today"); + + QUrl url = QUrl("http://api.sunrise-sunset.org/json"); + url.setQuery(urlQuery.toString()); + + QNetworkRequest request; + request.setUrl(url); + + QNetworkReply *reply = networkManagerGet(request); + m_timeReplies.append(reply); +} + +void DevicePluginDateTime::processTimesData(const QByteArray &data) +{ + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + + if(error.error != QJsonParseError::NoError) { + qCWarning(dcDateTime) << "failed to parse time JSON data:" << error.errorString() << ":" << data ; + return; + } + + QVariantMap response = jsonDoc.toVariant().toMap(); + if (response.value("status") != "OK") { + qCWarning(dcDateTime) << "failed to request time data:" << response.value("status"); + return; + } + + // given time is always in UTC + QVariantMap result = response.value("results").toMap(); + QString duskString = result.value("civil_twilight_begin").toString(); + QString sunriseString = result.value("sunrise").toString(); + QString noonString = result.value("solar_noon").toString(); + QString dawnString = result.value("civil_twilight_end").toString(); + QString sunsetString = result.value("sunset").toString(); + + m_dusk = QDateTime(QDate::currentDate(), QTime::fromString(duskString, "h:m:s AP"), Qt::UTC).toTimeZone(m_timeZone); + m_sunrise = QDateTime(QDate::currentDate(), QTime::fromString(sunriseString, "h:m:s AP"), Qt::UTC).toTimeZone(m_timeZone); + m_noon = QDateTime(QDate::currentDate(), QTime::fromString(noonString, "h:m:s AP"), Qt::UTC).toTimeZone(m_timeZone); + m_dawn = QDateTime(QDate::currentDate(), QTime::fromString(dawnString, "h:m:s AP"), Qt::UTC).toTimeZone(m_timeZone); + m_sunset = QDateTime(QDate::currentDate(), QTime::fromString(sunsetString, "h:m:s AP"), Qt::UTC).toTimeZone(m_timeZone); + + emit timeDataChanged(); +} + + +void DevicePluginDateTime::onTimeout() { QDateTime zoneTime = QDateTime::currentDateTime().toTimeZone(m_timeZone); + //qCDebug(dcDateTime) << m_timeZone.id() << zoneTime.toString(); - qCDebug(dcDateTime) << m_timeZone.id() << zoneTime.toString(); + if (zoneTime.date() != m_currentDateTime.date()) + emit dayChanged(); - if(deviceManager()->findConfiguredDevices(dateDeviceClassId).count() == 1){ - Device *device = deviceManager()->findConfiguredDevices(dateDeviceClassId).first(); - device->setStateValue(dayStateTypeId, zoneTime.date().day()); - device->setStateValue(monthStateTypeId, zoneTime.date().month()); - device->setStateValue(monthNameStateTypeId, zoneTime.date().longMonthName(zoneTime.date().month())); - device->setStateValue(monthNameShortStateTypeId, zoneTime.date().shortMonthName(zoneTime.date().month())); - device->setStateValue(yearStateTypeId, zoneTime.date().year()); - device->setStateValue(weekdayStateTypeId, zoneTime.date().dayOfWeek()); - device->setStateValue(weekdayNameStateTypeId, zoneTime.date().longDayName(zoneTime.date().dayOfWeek())); - device->setStateValue(weekdayNameShortStateTypeId, zoneTime.date().shortDayName(zoneTime.date().dayOfWeek())); + if (zoneTime.time().hour() != m_currentDateTime.time().hour()) + emit hourChanged(); - if(zoneTime.date().dayOfWeek() == 6 || zoneTime.date().dayOfWeek() == 7){ - device->setStateValue(weekendStateTypeId, true); - }else{ - device->setStateValue(weekendStateTypeId, false); - } + if (zoneTime.time().minute() != m_currentDateTime.time().minute()) + emit minuteChanged(); + + foreach (Device *device, deviceManager()->findConfiguredDevices(alarmDeviceClassId)) { + Alarm *alarm = m_alarms.value(device); + alarm->validateTimes(zoneTime); + } + + validateTimeTypes(zoneTime); + + // just store for compairing + m_currentDateTime = zoneTime; +} + +void DevicePluginDateTime::onAlarm() +{ + Alarm *alarm = static_cast(sender()); + Device *device = m_alarms.key(alarm); + + qCDebug(dcDateTime) << alarm->name() << "alarm!"; + + emit emitEvent(Event(alarmEventTypeId, device->id())); +} + +void DevicePluginDateTime::onTimeDataUpdate() +{ + // calculate the times in each alarm + qCDebug(dcDateTime) << " dusk :" << m_dusk.toString(); + qCDebug(dcDateTime) << " sunrise :" << m_sunrise.toString(); + qCDebug(dcDateTime) << " noon :" << m_noon.toString(); + qCDebug(dcDateTime) << " dawn :" << m_dawn.toString(); + qCDebug(dcDateTime) << " sunset :" << m_sunset.toString(); + qCDebug(dcDateTime) << "---------------------------------------------"; + + // alarms + foreach (Alarm *alarm, m_alarms.values()) { + alarm->setDusk(m_dusk); + alarm->setSunrise(m_sunrise); + alarm->setNoon(m_noon); + alarm->setDawn(m_dawn); + alarm->setSunset(m_sunset); + } + + // date + if (m_todayDevice != 0) + return; + + m_todayDevice->setStateValue(duskStateTypeId, m_dusk.toTime_t()); + m_todayDevice->setStateValue(sunriseStateTypeId, m_sunrise.toTime_t()); + m_todayDevice->setStateValue(noonStateTypeId, m_noon.toTime_t()); + m_todayDevice->setStateValue(dawnStateTypeId, m_dawn.toTime_t()); + m_todayDevice->setStateValue(sunsetStateTypeId, m_sunset.toTime_t()); + +} + +void DevicePluginDateTime::onMinuteChanged() +{ + QDateTime zoneTime = QDateTime::currentDateTime().toTimeZone(m_timeZone); + qCDebug(dcDateTime) << "minute changed" << zoneTime.toString(); + + // validate alerts + foreach (Device *device, deviceManager()->findConfiguredDevices(alarmDeviceClassId)) { + Alarm *alarm = m_alarms.value(device); + alarm->validate(zoneTime); + } +} + +void DevicePluginDateTime::onHourChanged() +{ + QDateTime zoneTime = QDateTime::currentDateTime().toTimeZone(m_timeZone); + qCDebug(dcDateTime) << "hour changed" << zoneTime.toString(); + + // check every hour in case we are offline in the wrong moment + searchGeoLocation(); +} + +void DevicePluginDateTime::onDayChanged() +{ + QDateTime zoneTime = QDateTime::currentDateTime().toTimeZone(m_timeZone); + qCDebug(dcDateTime) << "day changed" << zoneTime.toString(); + + if (m_todayDevice == 0) + return; + + m_todayDevice->setStateValue(dayStateTypeId, zoneTime.date().day()); + m_todayDevice->setStateValue(monthStateTypeId, zoneTime.date().month()); + m_todayDevice->setStateValue(yearStateTypeId, zoneTime.date().year()); + m_todayDevice->setStateValue(weekdayStateTypeId, zoneTime.date().dayOfWeek()); + m_todayDevice->setStateValue(weekdayNameStateTypeId, zoneTime.date().longDayName(zoneTime.date().dayOfWeek())); + m_todayDevice->setStateValue(monthNameStateTypeId, zoneTime.date().longMonthName(zoneTime.date().month())); + if(zoneTime.date().dayOfWeek() == 6 || zoneTime.date().dayOfWeek() == 7){ + m_todayDevice->setStateValue(weekendStateTypeId, true); + }else{ + m_todayDevice->setStateValue(weekendStateTypeId, false); } } @@ -195,12 +454,32 @@ void DevicePluginDateTime::onConfigValueChanged(const QString ¶mName, const if (newZone.isValid()) { m_timeZone = newZone; QDateTime zoneTime = QDateTime(QDate::currentDate(), QTime::currentTime(), m_timeZone); - qCDebug(dcDateTime) << "set new time zone:" << value.toString(); - qCDebug(dcDateTime) << "current time" << zoneTime.currentDateTime().toString(); + qCDebug(dcDateTime) << " time zone:" << value.toString(); + qCDebug(dcDateTime) << " current time:" << zoneTime.currentDateTime().toString(); qCDebug(dcDateTime) << "-----------------------------"; - timeout(); } else { qCWarning(dcDateTime) << "could not set new timezone" << value.toString() << ". keeping old time zone:" << m_timeZone; } + + // update everything with the new timezone + onTimeout(); } +void DevicePluginDateTime::validateTimeTypes(const QDateTime &dateTime) +{ + if (m_todayDevice == 0) { + return; + } + + if (dateTime == m_dusk) { + emit emitEvent(Event(duskEventTypeId, m_todayDevice->id())); + } else if (dateTime == m_sunrise) { + emit emitEvent(Event(sunriseEventTypeId, m_todayDevice->id())); + } else if (dateTime == m_noon) { + emit emitEvent(Event(noonEventTypeId, m_todayDevice->id())); + } else if (dateTime == m_dawn) { + emit emitEvent(Event(dawnEventTypeId, m_todayDevice->id())); + } else if (dateTime == m_sunset) { + emit emitEvent(Event(sunsetEventTypeId, m_todayDevice->id())); + } +} diff --git a/plugins/deviceplugins/datetime/deviceplugindatetime.h b/plugins/deviceplugins/datetime/deviceplugindatetime.h index ee6f9dff..46f3f102 100644 --- a/plugins/deviceplugins/datetime/deviceplugindatetime.h +++ b/plugins/deviceplugins/datetime/deviceplugindatetime.h @@ -22,8 +22,11 @@ #define DEVICEPLUGINDATETIME_H #include "plugin/deviceplugin.h" +#include "alarm.h" + #include #include +#include #include class DevicePluginDateTime : public DevicePlugin @@ -39,22 +42,58 @@ public: DeviceManager::HardwareResources requiredHardware() const override; QList configurationDescription() const override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; + void postSetupDevice(Device *device) override; void deviceRemoved(Device *device) override; - DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; + void networkManagerReplyReady(QNetworkReply *reply) override; void startMonitoringAutoDevices() override; - private: QTimer *m_timer; + Device *m_todayDevice; QTimeZone m_timeZone; + QDateTime m_currentDateTime; + + QHash m_alarms; + + QDateTime m_dusk; + QDateTime m_sunrise; + QDateTime m_noon; + QDateTime m_dawn; + QDateTime m_sunset; + + + QList m_locationReplies; + QList m_timeReplies; + + void searchGeoLocation(); + void processGeoLocationData(const QByteArray &data); + + void getTimes(const QString &latitude, const QString &longitude); + void processTimesData(const QByteArray &data); + +signals: + void dusk(); + void sunset(); + void noon(); + void sunrise(); + void dawn(); + void timeDataChanged(); + void minuteChanged(); + void hourChanged(); + void dayChanged(); private slots: - void timeout(); + void onTimeout(); + void onAlarm(); + void onTimeDataUpdate(); + void onMinuteChanged(); + void onHourChanged(); + void onDayChanged(); + void onConfigValueChanged(const QString ¶mName, const QVariant &value); - - + void validateTimeTypes(const QDateTime &dateTime); }; diff --git a/plugins/deviceplugins/datetime/deviceplugindatetime.json b/plugins/deviceplugins/datetime/deviceplugindatetime.json index 99003d63..81252e83 100644 --- a/plugins/deviceplugins/datetime/deviceplugindatetime.json +++ b/plugins/deviceplugins/datetime/deviceplugindatetime.json @@ -8,8 +8,8 @@ "deviceClasses": [ { "deviceClassId": "fbf665fb-9aca-423f-a5f2-924e50ebe6ca", - "idName": "date", - "name": "Date", + "idName": "today", + "name": "Today", "createMethods": ["auto"], "paramTypes": [ { @@ -40,13 +40,6 @@ "type": "QString", "defaultValue": "-" }, - { - "id": "4d0814f2-60a6-48c4-8b3b-031a099be8e3", - "idName": "monthNameShort", - "name": "month name short", - "type": "QString", - "defaultValue": "-" - }, { "id": "79d4ae9b-ea27-4346-8229-1d90f1ddfc9d", "idName": "year", @@ -68,19 +61,171 @@ "type": "QString", "defaultValue": "-" }, - { - "id": "7e8e8e53-a83b-493d-850d-b0407f03463a", - "idName": "weekdayNameShort", - "name": "weekday name short", - "type": "QString", - "defaultValue": "-" - }, { "id": "4de5b57b-bb1a-4d66-9ce3-22bb280b075d", "idName": "weekend", "name": "weekend", "type": "bool", "defaultValue": false + }, + { + "id": "44a99419-fbcd-4d8e-9441-897848b8f77c", + "idName": "dusk", + "name": "dusk", + "unit": "UnixTime", + "type": "int", + "defaultValue": 0 + }, + { + "id": "3a08824d-285b-412e-a515-9664b491a85c", + "idName": "sunrise", + "name": "sunrise", + "unit": "UnixTime", + "type": "int", + "defaultValue": 0 + }, + { + "id": "d92be29a-929c-4240-91a0-30153850f838", + "idName": "noon", + "name": "sun noon", + "unit": "UnixTime", + "type": "int", + "defaultValue": 0 + }, + { + "id": "a5779b11-0499-4a6d-a7bd-8143dcc546b4", + "idName": "dawn", + "name": "dawn", + "unit": "UnixTime", + "type": "int", + "defaultValue": 0 + }, + { + "id": "377f04a7-df58-42ad-a234-e9e23bdc2f85", + "idName": "sunset", + "name": "sunset", + "unit": "UnixTime", + "type": "int", + "defaultValue": 0 + } + ], + "eventTypes": [ + { + "id": "792885f3-f505-42db-8c74-3d0460b575a1", + "idName": "dusk", + "name": "dusk" + }, + { + "id": "792885f3-f505-42db-8c74-3d0460b575a1", + "idName": "sunrise", + "name": "sunrise" + }, + { + "id": "97ae8dd8-640c-4f9b-8773-aa7abb1d32fa", + "idName": "noon", + "name": "noon" + }, + { + "id": "5e3657b0-a459-4837-a632-0b20de4b7349", + "idName": "dawn", + "name": "dawn" + }, + { + "id": "f40d6e0f-fda2-475e-a6ae-c3fee03138b9", + "idName": "sunset", + "name": "sunset" + } + ] + }, + { + "deviceClassId": "3f3c7ecc-9915-4e4e-95a1-e11f4f9d174d", + "idName": "alarm", + "name": "Alarm", + "createMethods": ["user"], + "paramTypes": [ + { + "name": "name", + "type": "QString", + "inputType": "TextLine" + }, + { + "name": "monday", + "type": "bool", + "defaultValue": false + }, + { + "name": "tuesday", + "type": "bool", + "defaultValue": false + }, + { + "name": "wednesday", + "type": "bool", + "defaultValue": false + }, + { + "name": "thursday", + "type": "bool", + "defaultValue": false + }, + { + "name": "friday", + "type": "bool", + "defaultValue": false + }, + { + "name": "saturday", + "type": "bool", + "defaultValue": false + }, + { + "name": "sunday", + "type": "bool", + "defaultValue": false + }, + { + "name": "minutes", + "type": "int", + "unit": "Minutes", + "minValue": 0, + "maxValue": 60, + "defaultValue": 0 + }, + { + "name": "hours", + "type": "int", + "minValue": 0, + "maxValue": 24, + "unit": "Hours", + "defaultValue": 12 + }, + { + "name": "time type", + "type": "QString", + "allowedValues": [ + "time", + "dusk", + "sunrise", + "sunnoon", + "sunset", + "dawn" + ], + "defaultValue": "time" + }, + { + "name": "offset", + "type": "int", + "unit": "Minutes", + "minValue": -59, + "maxValue": 59, + "defaultValue": 0 + } + ], + "eventTypes": [ + { + "id": "5ec9a4af-d5ea-4f68-ab32-f7a3fcd75ccc", + "idName": "alarm", + "name": "alarm" } ] } diff --git a/plugins/deviceplugins/openweathermap/devicepluginopenweathermap.json b/plugins/deviceplugins/openweathermap/devicepluginopenweathermap.json index 85d34c20..d7889d7e 100644 --- a/plugins/deviceplugins/openweathermap/devicepluginopenweathermap.json +++ b/plugins/deviceplugins/openweathermap/devicepluginopenweathermap.json @@ -126,7 +126,7 @@ "idName": "sunset", "name": "sunset", "unit": "UnixTime", - "type": "uint", + "type": "int", "defaultValue": 0 }, { diff --git a/tests/auto/jsonrpc/testjsonrpc.cpp b/tests/auto/jsonrpc/testjsonrpc.cpp index 92d70afe..01a2389c 100644 --- a/tests/auto/jsonrpc/testjsonrpc.cpp +++ b/tests/auto/jsonrpc/testjsonrpc.cpp @@ -353,7 +353,6 @@ void TestJSONRPC::ruleAddedRemovedNotifications() QVariantMap stateEvaluator; stateEvaluator.insert("stateDescriptor", stateDescriptor); - // RuleAction QVariantMap actionNoParams; actionNoParams.insert("actionTypeId", mockActionIdNoParams);