21 #include <QMetaMethod> 29 #include "../notify/torcnotification.h" 37 int &Minutes,
int &Seconds, quint64 &DurationInSeconds)
46 QStringList initialsplit = Time.split(
'.');
47 QString dayshoursminutes = initialsplit[0];
48 QString secondss = initialsplit.size() > 1 ? initialsplit[1] : QStringLiteral(
"");
51 if (!secondss.isEmpty())
53 int newseconds = secondss.toInt(&ok);
56 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to parse seconds from '%1'").arg(secondss));
60 if (newseconds < 0 || newseconds > 59)
62 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid seconds value '%1'").arg(newseconds));
70 QStringList secondsplit = dayshoursminutes.split(
':');
71 int count = secondsplit.size();
74 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Cannot parse time from '%1'").arg(dayshoursminutes));
81 QString dayss = secondsplit[0].trimmed();
84 int newdays = dayss.toInt(&ok);
87 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to parse days from '%1'").arg(secondsplit[2]));
92 if (newdays < 0 || newdays > 365)
94 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid day value '%1'").arg(newdays));
105 QString hourss = secondsplit[count - 2].trimmed();
106 if (!hourss.isEmpty())
108 int newhours = hourss.toInt(&ok);
111 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to parse hours from '%1'").arg(secondsplit[1]));
115 if (newhours < 0 || newhours > 23)
117 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid hour value '%1'").arg(newhours));
126 QString minutess = secondsplit[count - 1].trimmed();
127 if (!minutess.isEmpty())
129 int newminutes = minutess.toInt(&ok);
132 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to parse minutes from '%1'").arg(secondsplit[0]));
136 if (newminutes < 0 || newminutes > 59)
138 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid minute values '%1'").arg(newminutes));
142 minutes = newminutes;
152 DurationInSeconds = seconds + (minutes * 60) + (hours * 60 * 60) + (days * 24 * 60 * 60);
158 return Days > 0 ? QStringLiteral(
"%1days %2").arg(Days).arg(QTime(0, 0).addSecs(Duration).toString(QStringLiteral(
"hh:mm.ss"))) :
159 QStringLiteral(
"%1").arg(QTime(0, 0).addSecs(Duration).toString(QStringLiteral(
"hh:mm.ss")));
162 #define BLACKLIST QStringLiteral("SetValue,SetValid,InputValueChanged,InputValidChanged") 171 :
TorcDevice(false, 0, 0, QStringLiteral(
"Control"), Details),
186 QVariantMap inputs = Details.value(QStringLiteral(
"inputs")).toMap();
187 QVariantMap::const_iterator it = inputs.constBegin();
188 for ( ; it != inputs.constEnd(); ++it)
189 if (it.key() == QStringLiteral(
"device"))
190 m_inputList.append(it.value().toString().trimmed());
194 QVariantMap outputs = Details.value(QStringLiteral(
"outputs")).toMap();
195 it = outputs.constBegin();
196 for (; it != outputs.constEnd(); ++it)
197 if (it.key() == QStringLiteral(
"device"))
204 QMutexLocker locker(&
lock);
216 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Control '%1' cannot have itself as input").arg(input));
223 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to find input '%1' for '%2'").arg(input,
uniqueId));
233 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Device '%1' does not recognise '%2' as an output")
246 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Control '%1' cannot have itself as output").arg(output));
253 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Failed to find output '%1' for device %2").arg(output,
uniqueId));
263 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Output '%1' (for control '%2') already has an owner")
272 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Device '%1' does not recognise '%2' as an input")
297 QMutexLocker locker(&
lock);
313 if (Output.isEmpty())
331 QMutexLocker locker(&
lock);
338 QStringList source = GetDescription();
339 foreach (
const QString &item, source)
349 QMap<QObject*,QString>::const_iterator it =
m_outputs.constBegin();
350 for ( ; it !=
m_outputs.constEnd(); ++it)
352 if (qobject_cast<TorcOutput*>(it.key()))
356 Data->append(QStringLiteral(
" \"%1\"->\"%2\"\r\n").arg(source, output->
GetUniqueId()));
358 else if (qobject_cast<TorcControl*>(it.key()))
363 else if (qobject_cast<TorcNotification*>(it.key()))
369 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Unknown output type"));
374 for ( ; it !=
m_inputs.constEnd(); ++it)
380 if (qobject_cast<TorcControl*>(it.key()))
382 else if (qobject_cast<TorcInput*>(it.key()))
385 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Unknown input type"));
387 Data->append(QStringLiteral(
" \"%1\"->\"%2\"\r\n").arg(inputid,
uniqueId));
408 QMutexLocker locker(&
lock);
410 QMap<QObject*,QString>::const_iterator it =
m_outputs.constBegin();
411 for ( ; it !=
m_outputs.constEnd(); ++it)
415 if (qobject_cast<TorcOutput*>(it.key()))
421 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Cannot set control '%1' as owner of output '%2'")
429 else if (qobject_cast<TorcControl*>(it.key()))
436 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Control '%1' does not recognise '%2' as an input")
444 else if (qobject_cast<TorcNotification*>(it.key()))
452 LOG(VB_GENERAL, LOG_INFO, QStringLiteral(
"Notification '%1' does not recognise '%2' as an input")
459 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Unknown output type for '%1'").arg(
uniqueId));
465 for ( ; it !=
m_inputs.constEnd(); ++it)
471 if (!control && !input)
473 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Unknown input type"));
480 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Control '%1' does not recognise control '%2' as an output")
498 LOG(VB_GENERAL, LOG_DEBUG, QStringLiteral(
"%1: Ready").arg(
uniqueId));
510 QMutexLocker locker(&
lock);
515 QObject *input = sender();
545 QMutexLocker locker(&
lock);
562 QMutexLocker locker(&
lock);
567 QObject* input = sender();
609 QMutexLocker locker(&
lock);
617 QMutexLocker locker(&
lock);
632 if (UniqueId.isEmpty())
634 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Invalid UniqueId"));
640 path += QStringLiteral(
"->");
644 QMap<QObject*,QString>::const_iterator it =
m_outputs.constBegin();
645 for ( ; it !=
m_outputs.constEnd(); ++it)
648 if (it.value() == UniqueId)
650 LOG(VB_GENERAL, LOG_ERR, QStringLiteral(
"Circular reference found: %1->%2").arg(path, UniqueId));
static bool ParseTimeString(const QString &Time, int &Days, int &Hours, int &Minutes, int &Seconds, quint64 &DurationInSeconds)
Parse a Torc time string into days, hours, minutes and, if present, seconds.
bool IsKnownInput(const QString &Input) const
void ValueChanged(double Value)
double GetDefaultValue(void)
virtual bool Validate(void)
void InputValidChangedPriv(QObject *Input, bool Valid)
virtual void SetValid(bool Valid)
void InputValidChanged(bool Valid)
QMap< QObject *, QString > m_inputs
virtual void CalculateOutput(void)=0
QMap< QObject *, double > m_inputValues
void InputValueChanged(double Value)
static QMutex * gDeviceListLock
virtual bool AllowInputs(void) const
Most controls have an input side.
void SubscriberDeleted(QObject *Subscriber)
QMap< QObject *, double > m_lastInputValues
void SetValid(bool Valid) override
static QHash< QString, TorcDevice * > * gDeviceList
virtual void SetValue(double Value)
void SetValue(double Value) override
static QString DurationToString(int Days, quint64 Duration)
bool IsKnownOutput(const QString &Output) const
void HandleSubscriberDeleted(QObject *Subscriber)
virtual bool IsPassthrough(void)
Only certain logic controls can be passthrough.
void Graph(QByteArray *Data)
Add this control to the state graph.
void CheckInputValues(void)
#define CONTROLS_DIRECTORY
QString GetUIName(void) override
bool Finish(void)
Finish setup of the control.
#define LOG(_MASK_, _LEVEL_, _STRING_)
bool CheckForCircularReferences(const QString &UniqueId, const QString &Path) const
QMap< QObject *, bool > m_inputValids
QString EnumToLowerString(T Value)
void ValidChanged(bool Valid)
QMap< QObject *, QString > m_outputs
virtual bool IsKnownInput(const QString &UniqueId)
bool SetOwner(QObject *Owner)
TorcControl(TorcControl::Type Type, const QVariantMap &Details)
QString GetUniqueId(void)