forked from donaloconnor/automon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rule.cpp
210 lines (163 loc) · 6.59 KB
/
rule.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
==================================================================================================
| rule.cpp |
| Part of the Automon application. |
| |
| Final Year Project - "An Embedded Automotive Monitoring Device" |
| |
| By Donal O' Connor for completion of B.Sc (Hons) Software Development and Computer Networking |
| Email: [email protected] |
| Website/Blog: http://automon.killarneyonline.eu |
| |
| Cork Institute of Technology, Cork, Ireland - http://www.cit.ie/ |
| |
| Copyright © 2009 Donal O'Connor <[email protected]> |
==================================================================================================
This is the implementation of the Rule class. More details below.
*/
#include "automon.h"
using namespace AutomonKernel;
Rule::Rule()
{
/* Create a script engine that will perform execution of our rule script */
m_scriptEngine = new QScriptEngine();
}
bool Rule::addSensor(Sensor * sensor)
{
/*
This method adds a sensor to our rule. For every sensor listed in our rule, it has to be added
*/
if (sensor == NULL)
{
/* Inputted sensor pointer is null so exit */
#ifdef DEBUGAUTOMON
qDebug() << "Invalid sensor";
#endif
return false;
}
/* Add the sensor pointer to our list of sensors */
m_sensors.append(sensor);
/* Create a regular string for our command name */
char commandName[1024];
/* Prepend our command, ie sensor 010D with an s, so we have s010D. This is required since variables
in EmeaScript (javascript) cannot start with a number
*/
QString copyIn = "s" + sensor->getCommand();
/* Copy the QString into our regular string */
strcpy(commandName, copyIn.toLatin1());
/* Create a QScriptValue object */
QScriptValue value(m_scriptEngine, 0.0);
/* Create a variable in our script engine of the name our sensor with the s and a value of 0.0 */
m_scriptEngine->globalObject().setProperty(commandName, value);
}
bool Rule::activate()
{
/*
This method is used to activate the rule so it starts listening to sensor's signals
and if the rule is satisfied it emits a signal
*/
bool found = false;
/* The rule is empty so return! */
if (m_rule.compare("") == 0)
return false;
/* For each sensor, ensure that no null pointers present */
for (int i = 0; i < m_sensors.size(); i++)
if (m_sensors[i] == NULL)
return false;
/* Get a list of the sensors in the rule string */
QStringList sensorNames;
sensorNames = m_rule.split(QRegExp("s"));
for (int i = 0; i < sensorNames.size(); i++)
if (sensorNames.at(i).compare("") != 0)
{
/* For each sensor that isn't NULL in the list, check if found in sensor list */
found = false;
for (int j = 0; j < m_sensors.size(); j++)
{
if (sensorNames.at(i).section("",0,4).compare(m_sensors.at(j)->getCommand()) == 0)
found = true; /* We have a match so safe */
}
if (!found)
return false; /* Sensor wasn't found in list so can't active so return */
}
/* Ensure that the script engine can evaulate the inputted rule */
if (!m_scriptEngine->canEvaluate(m_rule))
return false;
/* Connect each sensor's signal to this rule so we can get updates */
for (int i = 0; i < m_sensors.size(); i++)
connect(m_sensors[i], SIGNAL(changeOccurred(double)), this, SLOT(updateRule(double)));
/* Activation successful */
return true;
}
void Rule::updateRule(double value)
{
/*
This slot is called by each sensor in the rule when their values change.
We update the value of the corresponding sensor in the script engine and do check
*/
Sensor * senderSensor = static_cast<Sensor*>(QObject::sender());
char commandName[1024];
QString copyIn = "s" + senderSensor->getCommand();
strcpy(commandName, copyIn.toLatin1());
/* Set a new value to this */
QScriptValue scriptValue(m_scriptEngine, value);
/* Set the sXXXX sensor variable in the script engine to the value inputted */
m_scriptEngine->globalObject().setProperty(commandName, scriptValue);
/* Now do a check to see if the rule is satisfied */
checkIfSatisfied();
}
bool Rule::validateRule()
{
/* Ensures that the rule is not empty */
if (m_rule.compare("") == 0)
return false;
return true;
}
void Rule::setRule(QString rule)
{
/* A setter method to set the rule */
m_rule = rule;
}
void Rule::setRuleName(QString ruleName)
{
/* A setter to name the rule to an identifiable rule, like "Engine RPM < 30 AND Speed > 150 */
m_ruleName = ruleName;
}
QString Rule::getRule()
{
/* Return rule string */
return m_rule;
}
QString Rule::getRuleName()
{
/* Return rule human readable name */
return m_ruleName;
}
bool Rule::checkIfSatisfied()
{
/*
This method is used to check if the current rule string is satisfied after sensor values were updated
*/
/* Ensure that all sensors have updated first.
Coolant Temperature might not get updated for a few seconds so it's initial value is 0.
We will only validate rule when we have a proper up to date value of all sensors
*/
for (int i = 0; i < m_sensors.size(); i++)
{
if (m_sensors.at(i)->getChangeTimes() < 1)
return true;
}
/* Get the result of our rule expression */
bool ruleResult = m_scriptEngine->evaluate(m_rule.toLatin1()).toBoolean();
if (ruleResult != m_satisfied && ruleResult)
{
/* Rule satisfied, but only send update if not already */
m_satisfied = ruleResult;
sendAlert(m_ruleName);
} else if (!ruleResult)
{
/* Rule not satisfied */
m_satisfied = false;
}
return m_satisfied;
}