-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathSeismometer.cpp
129 lines (104 loc) · 2.95 KB
/
Seismometer.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
//
// Created by enrico on 12/07/15.
//
#include "common.h"
#include "Seismometer.h"
#include "Log.h"
#include "net/NTP.h"
#include "net/HTTPClient.h"
#include "LED.h"
#include "Utils.h"
#include "generic.h"
#include "net/TraceAccumulator.h"
Seismometer *Seismometer::instance = NULL;
Seismometer::Seismometer() {
lastEventWas = 0;
inEvent = false;
accelero = getAccelerometer();
}
void Seismometer::init() {
if (accelero == NULL) {
Log::e("Accelerometer is NULL");
}
}
void Seismometer::tick() {
if (accelero == NULL) {
return;
}
double detectionAVG = getCurrentAVG();
double detectionStdDev = getCurrentSTDDEV();
RECORD db = {0, 0, false};
db.ts = NTP::getUNIXTime();
db.accel = accelero->getTotalVector();
db.overThreshold = db.accel > quakeThreshold;
TraceAccumulator::traceValue(db.ts, db.accel, quakeThreshold, getCurrentAVG(), getCurrentSTDDEV(), getSigmaIter());
addValueToAvgVar(db.accel);
statLastCounter++;
if (Utils::millis() - statLastCounterTime > 1000) {
statProbeSpeed = statLastCounter;
statLastCounter = 0;
statLastCounterTime = Utils::millis();
}
if (inEvent && Utils::millis() - lastEventWas >= 5000) {
// Out of event
LED::red(false);
inEvent = false;
} else if (inEvent && Utils::millis() - lastEventWas < 5000) {
// In event, skipping detections for 5 seconds
return;
}
// if the values of the accelerometer have passed the threshold
// or if an "event" is currently running
if (db.overThreshold && !inEvent) {
Log::i("New Event: v:%lf - thr:%f - iter:%f - avg:%f - stddev:%f", db.accel, quakeThreshold,
getSigmaIter(), detectionAVG, detectionStdDev);
LED::red(true);
inEvent = true;
lastEventWas = Utils::millis();
HTTPClient::httpSendAlert(&db);
}
}
Seismometer *Seismometer::getInstance() {
if (Seismometer::instance == NULL) {
Seismometer::instance = new Seismometer();
}
return Seismometer::instance;
}
std::string Seismometer::getAccelerometerName() {
return accelero->getAccelerometerName();
}
unsigned int Seismometer::getStatProbeSpeed() {
return statProbeSpeed;
}
double Seismometer::getQuakeThreshold() {
return quakeThreshold;
}
void Seismometer::setSigmaIter(double i) {
this->sigmaIter = i;
}
void Seismometer::addValueToAvgVar(double val) {
elements++;
// https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
double delta = val - partialAvg;
partialAvg += delta / elements;
partialStdDev += delta * (val - partialAvg);
if (elements > 1) {
quakeThreshold = partialAvg + (getCurrentSTDDEV() * getSigmaIter());
}
//Log::d("AddValueToAvgVar: EL:%f D:%f AVG:%f VAR:%f THR:%f I:%i", val, delta, getCurrentAVG(), getCurrentSTDDEV(),
// quakeThreshold, elements);
}
void Seismometer::resetLastPeriod() {
partialAvg = 0;
partialStdDev = 0;
elements = 0;
}
double Seismometer::getSigmaIter() {
return sigmaIter;
}
double Seismometer::getCurrentAVG() {
return partialAvg;
}
double Seismometer::getCurrentSTDDEV() {
return sqrt(partialStdDev / (elements - 1));
}