From 26d9b258b442d17a2fd695bfbd88b6ea23105b11 Mon Sep 17 00:00:00 2001
From: joalhelk <joalhelk@jyu.fi>
Date: Mon, 12 Sep 2022 18:55:30 +0300
Subject: [PATCH] bug fixes

---
 .gitignore                                    |   1 +
 README.md                                     |   2 -
 .../watcherGui/Nodes/Node/Node.java           |   3 +-
 .../watcherGui/frames/WelcomePage.java        |  11 +-
 .../frames/panels/LineChartPanel.java         |   7 +-
 .../frames/subframes/AdminFrame.java          |   3 +-
 .../frames/subframes/Histograms.java          |  90 +++++++++++
 .../frames/subframes/NodeDataFrame.java       |   2 -
 .../frames/subframes/NodeSettingsFrame.java   |  21 ++-
 arduinoSensor/arduinoSensor.ino               | 145 ++++++++++--------
 arduinoSensor/measurements.cpp                |  39 +++++
 arduinoSensor/measurements.h                  |  28 ++++
 12 files changed, 259 insertions(+), 93 deletions(-)
 create mode 100644 WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/Histograms.java
 create mode 100644 arduinoSensor/measurements.cpp
 create mode 100644 arduinoSensor/measurements.h

diff --git a/.gitignore b/.gitignore
index 0d53eb5..1997183 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ arduino_secrets.h
 erikoistyö_raportti.pdf
 Työtunnit - Taulukko.pdf
 .DS_Store
+*.png
diff --git a/README.md b/README.md
index 458afb3..d5a9600 100644
--- a/README.md
+++ b/README.md
@@ -21,8 +21,6 @@ which it wants data. The user table has a array in it which contains the ID's of
 the subscribed nodes. The node table has info on the node, but there will be a
 subtable which contains nodeID, timestamp and attributes.
 
-## Technical info
-
 ## Future implementations
 Watcher should have the possibility to add friends to users friends list and
 possibly share their data.
diff --git a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/Nodes/Node/Node.java b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/Nodes/Node/Node.java
index e9e3a4c..92f9668 100644
--- a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/Nodes/Node/Node.java
+++ b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/Nodes/Node/Node.java
@@ -69,8 +69,7 @@ public class Node {
 		NodeData data = findRecentData(); 
 		if(data == null) return 0;
 		return data.getHumidity();
-	}
-	
+	}	
 
 	public Integer getRecentLuminosity() {
 		NodeData data = findRecentData();
diff --git a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/WelcomePage.java b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/WelcomePage.java
index 137d527..0d7b164 100644
--- a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/WelcomePage.java
+++ b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/WelcomePage.java
@@ -28,7 +28,7 @@ import com.joelhelkala.watcherGui.User.User;
 import com.joelhelkala.watcherGui.User.Roles.Role;
 import com.joelhelkala.watcherGui.frames.dialogs.Dialog;
 import com.joelhelkala.watcherGui.frames.subframes.AdminFrame;
-import com.joelhelkala.watcherGui.frames.subframes.FriendsFrame;
+import com.joelhelkala.watcherGui.frames.subframes.Histograms;
 import com.joelhelkala.watcherGui.frames.subframes.NodeDataFrame;
 import com.joelhelkala.watcherGui.frames.subframes.NodeSettingsFrame;
 import com.joelhelkala.watcherGui.frames.subframes.SettingsFrame;
@@ -57,7 +57,7 @@ public class WelcomePage implements MouseListener, ActionListener {
 	private JPanel stagePanel;
 	private final JLabel nodeDataLabel 		= new JLabel("Node data");
 	private final JLabel nodeSettingsLabel 	= new JLabel("Node settings");
-	private final JLabel friendsLabel 		= new JLabel("Friends");
+	private final JLabel friendsLabel 		= new JLabel("Histograms");
 	private final JLabel adminLabel 		= new JLabel("Admin");
 	private final JLabel helpLabel 			= new JLabel("Help");
 	private final JLabel settingsLabel 		= new JLabel("Settings");
@@ -69,6 +69,7 @@ public class WelcomePage implements MouseListener, ActionListener {
 	
 	private static NodeDataFrame nodeDataFrame = new NodeDataFrame(leftPanelWidth, topPanelHeight, width-leftPanelWidth, height-topPanelHeight-bottomPanelHeight);
 	private static NodeSettingsFrame nodeSettingFrame = new NodeSettingsFrame(width-leftPanelWidth, height-topPanelHeight-bottomPanelHeight);
+	private static Histograms histogramFrame = new Histograms();
 	
 	public WelcomePage(){		
 		frame = new JFrame();
@@ -187,12 +188,13 @@ public class WelcomePage implements MouseListener, ActionListener {
 		stagePanel.setBounds(leftPanelWidth, topPanelHeight, width-leftPanelWidth, height-topPanelHeight-bottomPanelHeight);
 		stagePanel.setBackground(Color.red);
 		
-		JPanel friendsFrame = new FriendsFrame(leftPanelWidth, topPanelHeight, width-leftPanelWidth, height-topPanelHeight-bottomPanelHeight);
+		//JPanel friendsFrame = new FriendsFrame(leftPanelWidth, topPanelHeight, width-leftPanelWidth, height-topPanelHeight-bottomPanelHeight);
 		JPanel settingsFrame = new SettingsFrame();
+
 		stagePanel.setLayout(cl);
 		stagePanel.add(nodeDataFrame, "data");
 		stagePanel.add(nodeSettingFrame, "setting");
-		stagePanel.add(friendsFrame, "friends");
+		stagePanel.add(histogramFrame, "friends");
 		stagePanel.add(settingsFrame, "settings");
 		
 		if(User.getRole() == Role.ADMIN) {
@@ -385,6 +387,7 @@ public class WelcomePage implements MouseListener, ActionListener {
 		node.updateData(HttpRequests.getNodeData(node.getId()));
 		nodeDataFrame.updateData(node);
 		nodeSettingFrame.updateInformation(node);
+		histogramFrame.updateData(node);
 	}
 	
 	/*
diff --git a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/panels/LineChartPanel.java b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/panels/LineChartPanel.java
index fcfc9fb..2b27d20 100644
--- a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/panels/LineChartPanel.java
+++ b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/panels/LineChartPanel.java
@@ -1,8 +1,8 @@
 package com.joelhelkala.watcherGui.frames.panels;
 
+import java.awt.BorderLayout;
 import java.awt.Dimension;
-import java.time.format.DateTimeFormatter;
-import java.time.format.FormatStyle;
+import java.util.List;
 
 import javax.swing.JPanel;
 
@@ -15,9 +15,6 @@ import org.jfree.data.category.DefaultCategoryDataset;
 
 import com.joelhelkala.watcherGui.Nodes.Node.NodeData.NodeData;
 
-import java.awt.BorderLayout;
-import java.util.List;
-
 public class LineChartPanel extends JPanel {
 	
 	private JFreeChart lineChart;
diff --git a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/AdminFrame.java b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/AdminFrame.java
index f53ad4c..23a8143 100644
--- a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/AdminFrame.java
+++ b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/AdminFrame.java
@@ -2,18 +2,17 @@ package com.joelhelkala.watcherGui.frames.subframes;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
-import java.util.List;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Insets;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.List;
 
 import javax.swing.Box;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JTextField;
 import javax.swing.SwingConstants;
diff --git a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/Histograms.java b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/Histograms.java
new file mode 100644
index 0000000..7097b4c
--- /dev/null
+++ b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/Histograms.java
@@ -0,0 +1,90 @@
+package com.joelhelkala.watcherGui.frames.subframes;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.util.ArrayList;
+
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.SpringLayout;
+
+import com.joelhelkala.watcherGui.Colors.Colors;
+import com.joelhelkala.watcherGui.Nodes.Node.Node;
+import com.joelhelkala.watcherGui.frames.panels.LineChartPanel;
+
+public class Histograms extends JPanel {
+	private LineChartPanel lumiChart;
+	private LineChartPanel moistChart;
+	private LineChartPanel tempChart;
+	
+	public Histograms() {
+		JScrollPane scroll = new JScrollPane();
+
+		JButton next = new JButton("Next");
+		JPanel buttonPanel = new JPanel();
+		buttonPanel.add(next);
+        SpringLayout layout = new SpringLayout();
+        JPanel mainPanel = new JPanel();
+        mainPanel.setLayout(null);
+        mainPanel.setBackground(Colors.gray);
+        setLayout(new BorderLayout());
+        
+        mainPanel.add(addTempChart(30, 0));
+        mainPanel.add(addLumiChart(30, 350));
+        mainPanel.add(addMoistChart(30, 700));
+        
+        
+        mainPanel.setPreferredSize(new Dimension(mainPanel.getWidth(), 1500));
+        scroll.setPreferredSize(new Dimension(500,500));
+        scroll.setViewportView(mainPanel);
+        scroll.setBackground(Colors.gray);
+        add(scroll);
+        add(buttonPanel,BorderLayout.SOUTH);
+
+        setSize(500, 600);
+        setVisible(true);
+	}
+	
+	private JPanel addMoistChart(int x, int y) {
+		JPanel chartPanel = new JPanel();
+		chartPanel.setBackground(Colors.errorText);
+		chartPanel.setBounds(x,y,800,300);
+		chartPanel.setLayout(new BorderLayout());
+		
+		moistChart = new LineChartPanel("Moisture", new ArrayList<>());
+		moistChart.setBackground(Colors.buttonColor);
+		chartPanel.add(moistChart, BorderLayout.CENTER);
+		return chartPanel;
+	}
+	
+	private JPanel addLumiChart(int x, int y) {
+		JPanel chartPanel = new JPanel();
+		chartPanel.setBackground(Colors.errorText);
+		chartPanel.setBounds(x,y,800,300);
+		chartPanel.setLayout(new BorderLayout());
+		
+		lumiChart = new LineChartPanel("Luminosity", new ArrayList<>());
+		lumiChart.setBackground(Colors.buttonColor);
+		chartPanel.add(lumiChart, BorderLayout.CENTER);
+		return chartPanel;
+	}
+	
+	private JPanel addTempChart(int x, int y) {
+		JPanel chartPanel = new JPanel();
+		chartPanel.setBackground(Colors.errorText);
+		chartPanel.setBounds(x,y,800,300);
+		chartPanel.setLayout(new BorderLayout());
+		
+		tempChart = new LineChartPanel("Temperature", new ArrayList<>());
+		tempChart.setBackground(Colors.buttonColor);
+		chartPanel.add(tempChart, BorderLayout.CENTER);
+		return chartPanel;
+	}
+	
+	public void updateData(Node node) {
+		tempChart.updateData(node.getData());
+		lumiChart.updateData(node.getData());
+		moistChart.updateData(node.getData());
+	}
+}
diff --git a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/NodeDataFrame.java b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/NodeDataFrame.java
index 476f076..bac2b5a 100644
--- a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/NodeDataFrame.java
+++ b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/NodeDataFrame.java
@@ -9,9 +9,7 @@ import com.joelhelkala.watcherGui.Nodes.Node.Node;
 import com.joelhelkala.watcherGui.frames.panels.HumidityPanel;
 import com.joelhelkala.watcherGui.frames.panels.LineChartPanel;
 import com.joelhelkala.watcherGui.frames.panels.LuminosityPanel;
-import com.joelhelkala.watcherGui.frames.panels.ProgressBarCirclePanel;
 import com.joelhelkala.watcherGui.frames.panels.TemperaturePanel;
-import com.joelhelkala.watcherGui.httpRequests.HttpRequests;
 
 public class NodeDataFrame extends JPanel {
 	
diff --git a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/NodeSettingsFrame.java b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/NodeSettingsFrame.java
index 15f2b45..ae91cf4 100644
--- a/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/NodeSettingsFrame.java
+++ b/WatcherGui/src/main/java/com/joelhelkala/watcherGui/frames/subframes/NodeSettingsFrame.java
@@ -36,35 +36,34 @@ public class NodeSettingsFrame extends JPanel implements ActionListener{
 	// Costructor
 	public NodeSettingsFrame(int width, int height) {
 		setLayout(null);
-		setBounds(0,0,width,height);
 		setOpaque(true);
 		setBackground(Colors.gray);
 		
 		JLabel descLabel = new JLabel("Description");
 		descLabel.setForeground(Color.white);
-		descLabel.setBounds(10,10, 100, 30);
-		descField.setBounds(120, 10, 200, 30);
+		descLabel.setBounds(width/2-200,40, 100, 30);
+		descField.setBounds(width/2-100, 40, 200, 30);
 		add(descLabel);
 		add(descField);
 		
 		JLabel locationLabel = new JLabel("Location");
 		locationLabel.setForeground(Color.white);
-		locationLabel.setBounds(10,50, 100, 30);
-		locationField.setBounds(120, 50, 200, 30);
+		locationLabel.setBounds(width/2-200,100, 100, 30);
+		locationField.setBounds(width/2-100, 100, 200, 30);
 		add(locationLabel);
 		add(locationField);
 		
 		JLabel latLabel = new JLabel("Latitude");
 		latLabel.setForeground(Color.white);
-		latLabel.setBounds(10,90, 100, 30);
-		latField.setBounds(120, 90, 200, 30);
+		latLabel.setBounds(width/2-200,160, 100, 30);
+		latField.setBounds(width/2-100, 160, 200, 30);
 		add(latLabel);
 		add(latField);
 		
 		JLabel lonLabel = new JLabel("Longitude");
 		lonLabel.setForeground(Color.white);
-		lonLabel.setBounds(10,130, 100, 30);
-		lonField.setBounds(120, 130, 200, 30);
+		lonLabel.setBounds(width/2-200,220, 100, 30);
+		lonField.setBounds(width/2-100, 220, 200, 30);
 		add(lonLabel);
 		add(lonField);
 		
@@ -73,8 +72,8 @@ public class NodeSettingsFrame extends JPanel implements ActionListener{
 		reset_btn.addActionListener(this);
 		save_btn.addActionListener(this);
 		
-		reset_btn.setBounds(width/4, height-200, 50, 20);
-		save_btn.setBounds(width/2, height-200, 50, 20);
+		reset_btn.setBounds(width/2-300, 300, 50, 20);
+		save_btn.setBounds(width/2+200, 300, 50, 20);
 		add(reset_btn);
 		add(save_btn);
 	}
diff --git a/arduinoSensor/arduinoSensor.ino b/arduinoSensor/arduinoSensor.ino
index 7238f6c..42ff76d 100644
--- a/arduinoSensor/arduinoSensor.ino
+++ b/arduinoSensor/arduinoSensor.ino
@@ -1,19 +1,10 @@
 /*
-  Repeating WiFi Web Client
-
- This sketch connects to a a web server and makes a request
- using a WiFi equipped Arduino board.
-
- created 23 April 2012
- modified 31 May 2012
- by Tom Igoe
- modified 13 Jan 2014
- by Federico Vanzati
-
- http://www.arduino.cc/en/Tutorial/WifiWebClientRepeating
- This code is in the public domain.
+ * This is a arduino program which measures environmental data
+ * and sends a measured average of these measurements to server.
+ *
+ * Joel Helkala
+ *
  */
-
 #include <SPI.h>
 #include <WiFiNINA.h>
 #include <ArduinoHttpClient.h>
@@ -25,7 +16,10 @@
 #include <Adafruit_BME280.h>
 #include "Adafruit_TSL2591.h"
 
+#include "measurements.h"
+#include <iostream>
 #include <vector>
+#include <chrono>
 
 // Initialize sensors
 Adafruit_BME280 bme; // BME sensor which has pressure, humidity and temperature
@@ -35,54 +29,69 @@ Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // Luminosity sensor
 char ssid[] = SECRET_SSID;        // your network SSID (name)
 char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
 
-int keyIndex = 0;            // your network key index number (needed only for WEP)
-
 int status = WL_IDLE_STATUS;
 boolean api_success = false;
 
 // server address:
-char server[] = "192.168.0.2";
-IPAddress server_ip(192,168,0,2);
+char server[] = "84.249.42.194";
+IPAddress server_ip(84,249,42,194);
 int port = 8080;
 
 // Initialize the WiFi client library
 WiFiClient client;
 HttpClient http = HttpClient(client, server, port);
 
-unsigned long lastConnectionTime = 0, lastMeasurement = 0;  // last time you connected to the server, in milliseconds
-const unsigned long postingInterval = 60L * 10L * 1000L;     // delay (60 * 10 * 1000 = 10 minutes) between updates, in milliseconds
-const unsigned long measurementInterval = 5L * 1000L;      // measure every 10 seconds
-
-struct Data {
-  int temp, humid, lumi;
-};
+//using namespace std::literals::chrono_literals;
+typedef std::chrono::high_resolution_clock Time;
 
-struct Measurements {
-  std::vector<Data> datas;
+struct Timer {
+  std::chrono::time_point<std::chrono::high_resolution_clock> lastConnectionTime, lastMeasurement;
+  const std::chrono::milliseconds postingInterval = std::chrono::milliseconds(1000 * 60 * 10); // 10 minutes
+  const std::chrono::milliseconds measurementInterval = std::chrono::milliseconds(1000 * 10);
+  int counter = 0;
 
-  void AddMeasurements(Data values) {
-    datas.push_back(values);
+  Timer() {
+    lastConnectionTime = std::chrono::high_resolution_clock::now();
+    lastMeasurement = std::chrono::high_resolution_clock::now();
   }
-
-  Data AverageAndClear() {
-    int temps = 0, humids = 0, lumis = 0;
-    
-    for(Data d : datas) {
-      temps += d.temp;
-      humids += d.humid;
-      lumis += d.lumi;
-    }
+  bool timeToPost() {
+    /*std::chrono::duration<float> duration = std::chrono::high_resolution_clock::now() - lastConnectionTime;
+    float durationMs = duration.count();
+    Serial.println(durationMs);
+    if (durationMs > postingInterval.count()) return true;
+    return false;*/
+    if (counter >= 10) return true;
+    return false;
+  }
+  bool timeToMeasure() {
+    std::chrono::duration<float> duration = Time::now() - lastMeasurement;
     
-    int amount = datas.size();
-    int av_temp = temps/amount;
-    int av_humid = humids/amount;
-    int av_lumi = lumis/amount;
-    datas.clear();
-    return Data{av_temp, av_humid, av_lumi};
+    float durationMs = duration.count() * 1000.0f;
+    if (durationMs > measurementInterval.count()) return true;
+    return false;
+  }
+  void resetConnectionTime() {
+    //lastConnectionTime = std::chrono::high_resolution_clock::now();
+    counter = 0;
+  }
+  void resetMeasurementTime() {
+    lastMeasurement = std::chrono::high_resolution_clock::now();
   }
 };
 
-Measurements measurements;
+struct Data {
+  int temp, humid, lumi;
+};
+
+void initPins() {
+  bme.begin(0x76);
+  tsl.begin();
+  tsl.setGain(TSL2591_GAIN_MED);
+  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
+}
+
+Watcher::Measurements measurements;
+Timer timer;
 
 void setup() {
   //Initialize serial and wait for port to open:
@@ -91,12 +100,7 @@ void setup() {
     ; // wait for serial port to connect. Needed for native USB port only
   }
 
-  // Initialize pins
-  bme.begin(0x76);
-  tsl.begin();
-  tsl.setGain(TSL2591_GAIN_MED);
-  tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
-  
+  initPins(); 
   // check for the WiFi module:
   if (WiFi.status() == WL_NO_MODULE) {
     Serial.println("Communication with WiFi module failed!");
@@ -116,8 +120,11 @@ void setup() {
   }
   // you're connected now, so print out the status:
   printWifiStatus();
+  timer.resetMeasurementTime();
+  timer.resetConnectionTime();
 }
 
+
 // MAIN LOOP
 void loop() {
   // if there's incoming data from the net connection.
@@ -128,31 +135,39 @@ void loop() {
     Serial.write(c);
   }
 
-  // Take measurements and add them to measurements
-  if(millis() - lastMeasurement > measurementInterval) {
-    int temp = bme.readTemperature();
-    int humidity = bme.readHumidity();
-    int luminosity = tsl.getLuminosity(TSL2591_VISIBLE);
-    measurements.AddMeasurements({temp, humidity, luminosity});
-    lastMeasurement = millis();
-  }
-  if (millis() - lastConnectionTime > postingInterval) {
+  // Take measurements and add them to list  
+  double temp = bme.readTemperature();
+  double humidity = bme.readHumidity();
+  double luminosity = tsl.getLuminosity(TSL2591_VISIBLE);
+  Watcher::measurement_t meas = {temp, humidity, luminosity};
+  Serial.print("Temperature: ");
+  Serial.println(meas.temperature);
+
+  measurements.addMeasurement(meas);
+  timer.counter++;
+  
+  
+  if (timer.timeToPost()) {
     httpRequest();
   }
+
+  delay(10000); // sleep for 10s to save power
 }
 
 void httpRequest() {
   // close any connection before send a new request.
   // This will free the socket on the NINA module
   Serial.println("making POST request");
-  Data average = measurements.AverageAndClear();
+  Watcher::measurement_t average = measurements.getAverage();
+  measurements.clear();
+  
   String contentType = "application/x-www-form-urlencoded";
   String postData ="temperature=";
-         postData += average.temp;
+         postData += average.temperature;
          postData += "&humidity=";
-         postData +=  average.humid;
+         postData +=  average.humidity;
          postData += "&luminosity=";
-         postData += average.lumi;
+         postData += average.luminosity;
          postData += "&parent_id=";
          postData += 1;
   
@@ -168,7 +183,7 @@ void httpRequest() {
   Serial.println(response);
   
   // note the time that the connection was made:
-  lastConnectionTime = millis();
+  timer.resetConnectionTime();
 }
 
 // Tulostetaan wifin tiedot
diff --git a/arduinoSensor/measurements.cpp b/arduinoSensor/measurements.cpp
new file mode 100644
index 0000000..ce42731
--- /dev/null
+++ b/arduinoSensor/measurements.cpp
@@ -0,0 +1,39 @@
+#include "measurements.h"
+#include <iostream>
+#include <vector>
+
+namespace Watcher {
+
+Measurements::Measurements() : Measurements(3) {}
+Measurements::Measurements(size_t size) {
+}
+
+Measurements::~Measurements() {
+  //
+}
+
+measurement_t Measurements::getAverage() const {
+  measurement_t average;
+  
+  for (auto measurement : _measurements_list) {
+    average.temperature += measurement.temperature;
+    average.humidity += measurement.humidity;
+    average.luminosity += measurement.luminosity;
+  }
+
+  size_t measurements_amount = _measurements_list.size();
+  average.temperature = average.temperature / measurements_amount;
+  average.humidity = average.humidity / measurements_amount;
+  average.luminosity = average.luminosity / measurements_amount;
+
+  return average;
+}
+
+void Measurements::clear() {
+  _measurements_list.clear();
+}
+
+void Measurements::addMeasurement(measurement_t &measurement) {
+  _measurements_list.emplace_back(measurement);
+}
+}
diff --git a/arduinoSensor/measurements.h b/arduinoSensor/measurements.h
new file mode 100644
index 0000000..46bd495
--- /dev/null
+++ b/arduinoSensor/measurements.h
@@ -0,0 +1,28 @@
+#ifndef Measurements_h
+#define Measurements_h
+
+#include <iostream>
+#include <chrono>
+#include <vector>
+
+namespace Watcher {
+
+struct measurement_t {
+  double temperature, humidity, luminosity;
+};
+
+class Measurements {
+public:
+  Measurements();
+  Measurements(size_t size);
+  ~Measurements();
+
+  measurement_t getAverage() const; 
+  void clear();
+  void addMeasurement(measurement_t &measurement);
+
+private:
+  std::vector<measurement_t> _measurements_list;
+};
+}
+#endif
-- 
GitLab