Torc  0.1
torccontrols.cpp
Go to the documentation of this file.
1 /* Class TorcControls
2 *
3 * Copyright (C) Mark Kendall 2015-18
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 
20 // Qt
21 #include <QMutex>
22 
23 // Torc
24 #include "torclogging.h"
25 #include "torccoreutils.h"
26 #include "torclogiccontrol.h"
27 #include "torctimercontrol.h"
28 #include "torctransitioncontrol.h"
29 #include "torccontrols.h"
30 
31 TorcControls* TorcControls::gControls = new TorcControls();
32 
33 #define BLACKLIST QStringLiteral("")
34 
35 TorcControls::TorcControls()
36  : QObject(),
37  TorcHTTPService(this, CONTROLS_DIRECTORY, QStringLiteral("controls"), TorcControls::staticMetaObject, BLACKLIST),
39  controlList(),
40  controlTypes()
41 {
42 }
43 
44 void TorcControls::Create(const QVariantMap &Details)
45 {
46  QWriteLocker locker(&m_handlerLock);
47 
48  QVariantMap::const_iterator it = Details.constFind(QStringLiteral("controls"));
49  if (Details.constEnd() == it)
50  return;
51 
52  QVariantMap control = it.value().toMap();
53  it = control.constBegin();
54  for ( ; it != control.constEnd(); ++it)
55  {
56  int type = TorcCoreUtils::StringToEnum<TorcControl::Type>(it.key());
57  if (type == -1)
58  {
59  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Unknown control type '%1'").arg(it.key()));
60  continue;
61  }
62 
63  QVariantMap controls = it.value().toMap();
64  QVariantMap::const_iterator it2 = controls.constBegin();
65  for ( ; it2 != controls.constEnd(); ++it2)
66  {
67  QVariantMap details = it2.value().toMap();
68  if (!details.contains(QStringLiteral("name")))
69  {
70  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Ignoring control type '%1' with no <name>").arg(TorcCoreUtils::EnumToLowerString<TorcControl::Type>((TorcControl::Type)type)));
71  continue;
72  }
73 
74  switch ((TorcControl::Type)type)
75  {
76  case TorcControl::Logic: controlList.append(new TorcLogicControl(it2.key(), details)); break;
77  case TorcControl::Timer: controlList.append(new TorcTimerControl(it2.key(), details)); break;
78  case TorcControl::Transition: controlList.append(new TorcTransitionControl(it2.key(), details)); break;
79  default: break;
80  }
81  }
82  }
83 }
84 
85 void TorcControls::Destroy(void)
86 {
87  QWriteLocker locker(&m_handlerLock);
88 
89  foreach (TorcControl *control, controlList)
90  control->DownRef();
91  controlList.clear();
92 }
93 
94 void TorcControls::Validate(void)
95 {
96  QWriteLocker locker(&m_handlerLock);
97 
98  // We first validate each control.
99 
100  // At this point all sensors, controls and outputs have been parsed successfully and
101  // the objects created.
102  // Validation checks each control has the correct number of valid inputs and outputs and then
103  // connects the appropriate signal/slot pairs. At this point no signals should be triggered.
104 
105  QMutableListIterator<TorcControl*> it(controlList);
106  while (it.hasNext())
107  {
108  TorcControl* control = it.next();
109  if (!control->Validate())
110  {
111  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to complete device '%1' - deleting").arg(control->GetUniqueId()));
112  control->DownRef();
113  it.remove();
114  }
115  else
116  {
117  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Registered control '%1'").arg(control->Name()));
118  }
119  }
120 
121  LOG(VB_GENERAL, LOG_DEBUG, QStringLiteral("Controls validated"));
122 
123  // Each control now has a complete list of inputs and outputs so we can now check for circular references.
124  // N.B. Only controls are aware of other devices (i.e. they are created with the expectation that they are
125  // connected to sensors/outputs/other controls. Sensors and outputs are notionally standalone.
126 
127  // Iterate over the controls list and recursively check for circular references.
128  foreach (TorcControl* control, controlList)
129  {
130  QString id = control->GetUniqueId();
131  QString path(QStringLiteral(""));
132  (void)control->CheckForCircularReferences(id, path);
133  }
134 }
135 
136 void TorcControls::Graph(QByteArray* Data)
137 {
138  if (Data)
139  foreach(TorcControl *control, controlList)
140  control->Graph(Data);
141 }
142 
143 QString TorcControls::GetUIName(void)
144 {
145  return tr("Controls");
146 }
147 
148 void TorcControls::SubscriberDeleted(QObject *Subscriber)
149 {
151 }
152 
154 {
155  QReadLocker locker(&m_handlerLock);
156 
157  QVariantMap result;
158  QMetaEnum meta = QMetaEnum::fromType<TorcControl::Type>();
159  for (int count = meta.keyCount() - 1 ; count >= 0; --count)
160  {
161  TorcControl::Type type = (TorcControl::Type)meta.value(count);
162  QStringList controlsfortype;
163  foreach (TorcControl *control, controlList)
164  if (control->GetType() == type)
165  controlsfortype.append(control->GetUniqueId());
166 
167  if (!controlsfortype.isEmpty())
168  result.insert(TorcCoreUtils::EnumToLowerString<TorcControl::Type>(static_cast<TorcControl::Type>(type)), controlsfortype);
169  }
170  return result;
171 }
172 
174 {
175  return TorcCoreUtils::EnumList<TorcControl::Type>();
176 }
177 
QStringList GetControlTypes(void)
#define BLACKLIST
virtual bool Validate(void)
void SubscriberDeleted(QObject *Subscriber)
virtual TorcControl::Type GetType(void) const =0
virtual bool DownRef(void)
QString Name(void) const
QVariantMap GetControlList(void)
void HandleSubscriberDeleted(QObject *Subscriber)
void Graph(QByteArray *Data)
Add this control to the state graph.
#define CONTROLS_DIRECTORY
Definition: torccontrol.h:13
QVariantMap controlList
Definition: torccontrols.h:15
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: torclogging.h:20
bool CheckForCircularReferences(const QString &UniqueId, const QString &Path) const
QReadWriteLock m_handlerLock
QString GetUniqueId(void)
Definition: torcdevice.cpp:162