HomeWaterLeaksDetection
main.cpp
Go to the documentation of this file.
1 #include "Arduino.h"
2 #include "vector"
3 #include "SPI.h"
4 #include "SD.h"
5 
6 #include "Setup.h"
7 #include "Pins.h"
8 #include "LimitsDefinition.h"
9 #include "DateTime.h"
10 #include "EmailSender.h"
11 #include "DailyOverview.h"
12 
13 #include "FreeMemoryMeasurement.h"
14 
15 #ifdef GENERATE_PULSES
16 # include <PulseGenerator.h>
17 #endif
18 
19 #include "PulseCounter.h"
20 #include "LeaksController.h"
21 #include "ALeakDetectable.h"
22 #include "LeakDetectionConfig.h"
23 #include "HighLeakDetection.h"
24 #include "LowLeakDetection.h"
25 #include "TotalLeakDetection.h"
26 
27 #ifdef DEBUG
28 # include <ILoggable.h>
29 # include <IControllable.h>
30 # include <Logger.h>
31 #endif
32 
33 #ifdef WEB_SERVER
34 # include <HTMLDataSource.h>
35 # include <WebServer.h>
36 # include <Consumption.h>
37 #endif
38 
39 #ifdef LCD_DISPLAY
40 # include <LCDController.h>
41 # include <FreeMemoryMeasurement.h>
42 #endif
43 
44 #ifdef GENERATE_PULSES
45  PulseGenerator pulseGenerator(PG_DELAY_HIGH, PG_DELAY_LOW, PG_PIN);
46 #endif
47 
49 std::vector<IControllable *> controllers; // collection of all controllers
50 
51 HighLeakDetection *highLeakDetection; // high-water leak detection algorithm
52 LowLeakDetection *lowLeakDetection; // low-water leak detection algorithm
53 TotalLeakDetection *totalLeakDetection; // total-water leak detection algorithm
54 
55 // initializes all three algorithms with
56 // the default values as defined in LimitsDefinition.h
58  // high-water leak detection algorithm
60  &pulseCounter,
64 
65  // low-water leak detection algorithm
67  &pulseCounter,
71 
72  // total-water leak detection algorithm
74  &pulseCounter,
78 }
79 
80 // splits the string given as a parameter by ';'
81 // and returns the tokens in a vector
82 std::vector<String> split(String& data) {
83  std::vector<String> tokens;
84  String buffer = "";
85  for (int i = 0; i < (int)data.length(); i++) {
86  if (data[i] == ';') {
87  tokens.push_back(buffer);
88  buffer = "";
89  }
90  else buffer += data[i];
91  }
92  return tokens;
93 }
94 
95 // initializes the water-leak detection
96 // algorithm with the data from the file
97 // stored on the SD card
98 int createHighLeakDetection(String data) {
99  std::vector<String> tokens = split(data);
100 
101  // make sure there's exactly 4 values
102  // in the file - limit,reset (normal ,alaram)
103  if (tokens.size() != 4)
104  return 0;
105 
107  &pulseCounter,
109  {strtoul(tokens[0].c_str(), NULL, 10), UNUSED, atoi(tokens[1].c_str()), HIGH_BYPASS_PIN},
110  {strtoul(tokens[2].c_str(), NULL, 10), UNUSED, atoi(tokens[3].c_str()), HIGH_BYPASS_PIN}
111  );
112  return 1; // everything's okay
113 }
114 
115 // initializes the low-leak detection
116 // algorithm with the data from the file
117 // stored on the SD card
118 int createLowLeakDetection(String data) {
119  std::vector<String> tokens = split(data);
120 
121  // make sure there's exactly 4 values
122  // in the file - limit,reset (normal ,alaram)
123  if (tokens.size() != 4)
124  return 0;
125 
127  &pulseCounter,
129  {strtoul(tokens[0].c_str(), NULL, 10), strtoul(tokens[1].c_str(), NULL, 10), UNUSED, LOW_BYPASS_PIN},
130  {strtoul(tokens[2].c_str(), NULL, 10), strtoul(tokens[3].c_str(), NULL, 10), UNUSED, LOW_BYPASS_PIN}
131  );
132  return 1; // everything's okay
133 }
134 
135 // initializes the total-leak detection
136 // algorithm with the data from the file
137 // stored on the SD card
138 int createTotalLeakDetection(String data) {
139  std::vector<String> tokens = split(data);
140 
141  // make sure there's exactly 4 values
142  // in the file - limit,reset (normal ,alaram)
143  if (tokens.size() != 4)
144  return 0;
145 
147  &pulseCounter,
149  {strtoul(tokens[0].c_str(), NULL, 10), UNUSED, atoi(tokens[1].c_str()), TOTAL_BYPASS_PIN},
150  {strtoul(tokens[2].c_str(), NULL, 10), UNUSED, atoi(tokens[3].c_str()), TOTAL_BYPASS_PIN}
151  );
152  return 1; // everything's okay
153 }
154 
155 // initializes the e-mail notification
156 // settings with the data from the file
157 // stored on the SD card
158 int setSettingsNotification(String data) {
159  #ifdef EMAIL_NOTIFICATION
160  std::vector<String> tokens = split(data);
161 
162  // make sure there's exactly mailSender::Type::COUNT + 1
163  // on the particular line in the settings file
164  if (tokens.size() != EmailSender::Type::COUNT + 1)
165  return 0;
166 
167  // apply the settings
178  #endif
179  return 1; // everything's okay
180 }
181 
182 void loadSettings() {
183  #ifdef DEBUG
184  Serial.println("loading settings...");
185  #endif
186 
187  // if the SD card is not avaliable,
188  // apply the default settings of all
189  // three water leak detection algorithms
190  if (!SD.begin(SS_SD_CARD)) {
191  #ifdef DEBUG
192  Serial.println("ERROR - SD card initialization failed!");
193  #endif
195  return;
196  }
197 
198  pinMode(SS_SD_CARD, OUTPUT);
199  pinMode(SS_ETHERNET, OUTPUT);
200  digitalWrite(SS_SD_CARD, HIGH); // SD Card not active
201  digitalWrite(SS_ETHERNET, HIGH); // Ethernet not active
202 
203  // search for the settings file on the SD card
204  File settingsFile = SD.open(SETTINGS_FILE_NAME);
205 
206  if (settingsFile) {
207  // if the any of the lines of the settings file doesn't
208  // have the right syntax, automatically apply the default
209  // settings for all three water-leak detection algorithms
210  if (!createHighLeakDetection(settingsFile.readStringUntil('\n')) ||
211  !createLowLeakDetection(settingsFile.readStringUntil('\n')) ||
212  !createTotalLeakDetection(settingsFile.readStringUntil('\n')) ||
213  !setSettingsNotification(settingsFile.readStringUntil('\n')))
214  {
216  }
217  settingsFile.close(); // close the config file
218 
219  } else {
220  #ifdef DEBUG
221  Serial.print("error opening ");
222  Serial.println(SETTINGS_FILE_NAME);
223  #endif
224  applyDefaultSettings(); // apply the default settings
225  }
226 }
227 
228 void setup() {
229  // enable the serial communication
230  // for the terminal (debugging)
231  Serial.begin(SERIAL_BAUD_RATE);
232  while (!Serial)
233  ;
234 
235  DateTime::getInstance(); //setup the datetime
236 
237  #ifdef DEBUG
238  Serial.println("<[STARTING PROGRAM]>");
239  Serial.println("pins configuration...");
240  #endif
241 
242  CONFIG_PINS // configure pins
243  loadSettings(); // load setting off the SD card
244 
245  // initialize the logging part of the system
246  #ifdef DEBUG
247  Serial.println("adding instances to logging...");
253  controllers.push_back(Logger::getInstance());
254  #endif
255 
256  // initialize all controllers of the system
257  #ifdef DEBUG
258  Serial.println("adding instances of all the controllers...");
259  #endif
265 
266  // initialize the LCD display (what pages will be displayed)
267  #ifdef LCD_DISPLAY
272  //LCDController::getInstance()->addItem(FreeMemoryMeasurement::getInstance());
274  #ifdef DEBUG
276  #endif
277  #endif
278 
279  // initialize the webserver
280  #ifdef WEB_SERVER
281  #ifdef DEBUG
282  Serial.println("web server initialization...");
283  #endif
284 
285  // set HTML data sources
294 
295  controllers.push_back(WebServer::getInstance());
296 
297  // monitoring of water consumption
298  Consumption *dailyWaterConsumption = new Consumption(&pulseCounter, Consumption::DAY);
299  Consumption *monthlyWaterConsumption = new Consumption(&pulseCounter, Consumption::MONTH);
300 
303 
305  #endif
306 
307  // initialize the daily overview class
308  #ifdef LCD_DISPLAY
309  DailyOverview *dailyOverview = new DailyOverview(highLeakDetection, // high-water algo.
310  lowLeakDetection, // low-water algo.
311  totalLeakDetection, // total-water algo.
312  dailyWaterConsumption, // daily consump.
313  monthlyWaterConsumption); // monthly consump.
314  controllers.insert(controllers.begin(), dailyOverview);
315  LCDController::getInstance()->addItem(dailyOverview);
316  #endif
317 
318  #ifdef DEBUG
319  Serial.println("program is now running...");
320  #endif
321 
322  // send an e-mail that the device has started
323  #ifdef EMAIL_NOTIFICATION
326  "Home Water Leaks Detection",
327  "The device is now running\n\r"
328  "start time: " + DateTime::getInstance()->getDateTimeStr());
329  #endif
330 }
331 
332 void loop() {
333 // WARNING doesn't work correctly when the user requests to open the website
334 // because it's not included the the class LeakController that is updated
335 // independently while the website is being loaded. This is only for
336 // testing purposes anyway.
337 #ifdef GENERATE_PULSES
338  pulseGenerator.update();
339 #endif
340 
341  // update all the constrollers of the system
342  for (const auto controller : controllers)
343  controller->update();
344 }
EmailSender::CHANGED_SETTINGS
@ CHANGED_SETTINGS
when the user changes settings
Definition: EmailSender.h:51
loop
void loop()
Definition: main.cpp:332
DailyOverview
Definition: DailyOverview.h:27
LeakDetectionConfig.h
ALeakDetectable::Total
@ Total
total water leak detection algorithm
Definition: ALeakDetectable.h:60
Pins.h
lowLeakDetection
LowLeakDetection * lowLeakDetection
Definition: main.cpp:52
LeaksController::addLeakDetection
void addLeakDetection(ALeakDetectable::Type type, ALeakDetectable *leak)
Adds another water leak detection algorithm to the collection.
Definition: LeaksController.cpp:33
EmailSender::BYPASS
@ BYPASS
when a bypass changes
Definition: EmailSender.h:53
highLeakDetection
HighLeakDetection * highLeakDetection
Definition: main.cpp:51
Consumption.h
setup
void setup()
Definition: main.cpp:228
pulseCounter
PulseCounter pulseCounter(SENSOR_PIN)
SS_SD_CARD
#define SS_SD_CARD
SD card pin (arduino documentation)
Definition: Setup.h:30
Logger::getInstance
static Logger * getInstance()
Returns the instance of the class.
Definition: Logger.cpp:5
ALeakDetectable::Low
@ Low
low water leak detection algorithm
Definition: ALeakDetectable.h:58
setSettingsNotification
int setSettingsNotification(String data)
Definition: main.cpp:158
applyDefaultSettings
void applyDefaultSettings()
Definition: main.cpp:57
DateTime.h
split
std::vector< String > split(String &data)
Definition: main.cpp:82
HIGH_BYPASS_PIN
#define HIGH_BYPASS_PIN
high-water leak bypass button
Definition: Pins.h:25
createTotalLeakDetection
int createTotalLeakDetection(String data)
Definition: main.cpp:138
EmailSender::enableNotification
void enableNotification(Type type, bool state)
Enables/disables the particular type of e-mail notification.
Definition: EmailSender.cpp:43
SETTINGS_FILE_NAME
#define SETTINGS_FILE_NAME
the main settings file stored on the SD card
Definition: Setup.h:27
ILoggable.h
LeaksController::setMonthlyConsumptionCounter
void setMonthlyConsumptionCounter(Consumption *monthlyConsumptionCounter)
Sets an instance of Consumption (monthly water consumption)
Consumption::MONTH
@ MONTH
monthly water consumption
Definition: Consumption.h:22
SERIAL_BAUD_RATE
#define SERIAL_BAUD_RATE
baud rate for the serial communication (terminal)
Definition: Setup.h:25
LowLeakDetection.h
TotalLeakDetection
Definition: TotalLeakDetection.h:15
ALeakDetectable.h
EmailSender::BOOTING
@ BOOTING
when the system boots up
Definition: EmailSender.h:45
HighLeakDetection
Definition: HighLeakDetection.h:23
createLowLeakDetection
int createLowLeakDetection(String data)
Definition: main.cpp:118
PulseGenerator
Definition: PulseGenerator.h:19
HTMLDataSource.h
Logger.h
EmailSender.h
ALeakDetectable::High
@ High
high water leak detection algorithm
Definition: ALeakDetectable.h:59
Setup.h
loadSettings
void loadSettings()
Definition: main.cpp:182
LCDController::addItem
void addItem(IDisplayable *item)
Adds another source of data for the LCD display (another class)
Definition: LCDController.cpp:16
createHighLeakDetection
int createHighLeakDetection(String data)
Definition: main.cpp:98
LimitsDefinition.h
LeaksController.h
EmailSender::setReceiverEmailAddress
void setReceiverEmailAddress(String email)
Changes the user's e-mail address.
Definition: EmailSender.cpp:83
CONFIG_PINS
#define CONFIG_PINS
Definition: Pins.h:37
LOW_BYPASS_PIN
#define LOW_BYPASS_PIN
low-water leak bypass button
Definition: Pins.h:29
controllers
std::vector< IControllable * > controllers
Definition: main.cpp:49
TotalLeakDetection.h
DateTime::getInstance
static DateTime * getInstance()
Returns the instance of the class.
Definition: DateTime.cpp:26
EmailSender::LEAK_DETECTED
@ LEAK_DETECTED
when a leak has been detected
Definition: EmailSender.h:47
totalLeakDetection
TotalLeakDetection * totalLeakDetection
Definition: main.cpp:53
HighLeakDetection.h
WebServer::addHTMLSource
void addHTMLSource(HTMLDataSource *source)
Adds another source of data for the HTML content.
Definition: WebServer.cpp:90
Consumption
Definition: Consumption.h:13
TOTAL_LEAK_NORMAL_DEFAULT_CONFIG
#define TOTAL_LEAK_NORMAL_DEFAULT_CONFIG
Passes the default total-water leak detection parameters to the constructor.
Definition: LimitsDefinition.h:53
LeaksController::setDailyConsumptionCounter
void setDailyConsumptionCounter(Consumption *dailyConsumptionCounter)
Sets an instance of Consumption (daily water consumption)
LCDController.h
FreeMemoryMeasurement::getInstance
static FreeMemoryMeasurement * getInstance()
Returns the instance of the class.
Definition: FreeMemoryMeasurement.cpp:15
EmailSender::sendEmail
byte sendEmail(String subject, String data)
Sends an e-mail off to the smtp2go server.
Definition: EmailSender.cpp:93
LeaksController::setPulseCounter
void setPulseCounter(PulseCounter *pulseCounter)
Sets an instance of PulseCounter.
Definition: LeaksController.cpp:90
SS_ETHERNET
#define SS_ETHERNET
etherent pin (arduino documentation)
Definition: Setup.h:31
EmailSender::VALVE_STATE
@ VALVE_STATE
when the state of the valve has changed
Definition: EmailSender.h:48
EmailSender::RESET
@ RESET
when the device resets
Definition: EmailSender.h:49
EmailSender::APPLIED_NEW_SETTING
@ APPLIED_NEW_SETTING
when the new settings are applied
Definition: EmailSender.h:52
Logger::addEntity
void addEntity(ILoggable *log)
Adds another class to the logging system.
Definition: Logger.cpp:10
WebServer.h
PulseCounter
Definition: PulseCounter.h:29
LCDController::getInstance
static LCDController * getInstance()
Returns the instance of the class.
Definition: LCDController.cpp:10
TOTAL_BYPASS_PIN
#define TOTAL_BYPASS_PIN
total-water leak bypass button
Definition: Pins.h:33
IControllable.h
PulseCounter.h
WebServer::getInstance
static WebServer * getInstance()
Returns the instance of the class.
Definition: WebServer.cpp:9
PulseGenerator.h
HIGH_LEAK_NORMAL_DEFAULT_CONFIG
#define HIGH_LEAK_NORMAL_DEFAULT_CONFIG
Passes the default high-water leak detection parameters to the constructor.
Definition: LimitsDefinition.h:39
DailyOverview.h
LOW_LEAK_NORMAL_DEFAULT_CONFIG
#define LOW_LEAK_NORMAL_DEFAULT_CONFIG
Passes the default low-water leak detection parameters to the constructor.
Definition: LimitsDefinition.h:46
FreeMemoryMeasurement.h
SENSOR_PIN
#define SENSOR_PIN
the flow sensor
Definition: Pins.h:10
LeaksController::getInstance
static LeaksController * getInstance()
Returns the instance of the class.
Definition: LeaksController.cpp:27
EmailSender::DAILY_OVERVIEW
@ DAILY_OVERVIEW
daily overview about the system
Definition: EmailSender.h:46
EmailSender::ALARM
@ ALARM
when the state of the home alarm changes
Definition: EmailSender.h:50
Consumption::DAY
@ DAY
daily water consumption
Definition: Consumption.h:20
LowLeakDetection
Definition: LowLeakDetection.h:21
UNUSED
#define UNUSED
unused parameter
Definition: LimitsDefinition.h:19
EmailSender::getInstance
static EmailSender * getInstance()
Returns the instance of the class.
Definition: EmailSender.cpp:87
WebServer::setup
void setup(LeaksController *leaksController)
Sets the pointer to an instance of LeaksController.
Definition: WebServer.cpp:41