-
Notifications
You must be signed in to change notification settings - Fork 5
/
galileo-core.cpp
281 lines (230 loc) · 6.36 KB
/
galileo-core.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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#ifndef __GALILEO_CORE_CPP
#define __GALILEO_CORE_CPP
#include <stdlib.h>
#include <stdint.h>
#include <execinfo.h>
#include <sys/fcntl.h>
#include <string.h>
#include "common.h"
#include "Config.h"
#include "Log.h"
#include "LED.h"
#include "Utils.h"
#include "net/NTP.h"
#include "net/NetworkManager.h"
#include "CommandInterface.h"
#include "generic.h"
#include "net/HTTPClient.h"
#ifndef NOWATCHDOG
#include "Watchdog.h"
#endif
// Seismometer instance
Seismometer *seismometer;
/**
* In some platforms there is no support to multiprocess/multithread, so the
* "trick" is to execute a loop() function in-loop and measure the time passed
* from last execution.
* These variables are the last timestamp of execution
*/
unsigned long netLastMs = 0;
unsigned long ntpLastMs = 0;
unsigned long cfgLastMs = 0;
unsigned long seismoLastMs = 0;
unsigned long logRotationMs = 0;
#ifdef DEBUG
unsigned long valgrindMs = 0;
#endif
void setup();
void loop();
#ifdef DEBUG
/**
* Crash handler (debug-only) - for post-mortem debug
*/
void crashHandler(int sig) {
void *array[10];
// get void*'s for all entries on the stack
int size = backtrace(array, 10);
// print out all the frames to stderr
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
int fd = open(STACKTRACEINFO, O_RDWR | O_TRUNC);
if (fd < 0) {
// Ooops! Cannot create stack trace info
exit(1);
}
std::string sigError = "Error: signal " + Utils::toString(sig);
write(fd, sigError.c_str(), sigError.length());
backtrace_symbols_fd(array, size, fd);
close(fd);
exit(1);
}
#endif
/**
* Entry point
*/
int main(int argc, char **argv) {
// Vendor init (for example, Galileo platform needs to execute some syscalls before the sketch)
vendor_init(argc, argv);
#ifdef DEBUG
if (argc > 1 && strcmp("--valgrind", argv[1]) == 0) {
// Valgrind dummy configuration
valgrindMs = Utils::millis();
HTTPClient::setBaseURL("https://192.0.2.20/seismocloud/");
Config::setMacAddress("000000000000");
Config::setLatitude(0.1);
Config::setLongitude(0.1);
} else if (argc > 1 && strcmp("--raw", argv[1]) == 0) {
// Raw dumper
Accelerometer *accel = getAccelerometer();
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-noreturn"
while (true) {
if (Utils::millis() - seismoLastMs >= SEISMOMETER_TICK_INTERVAL) {
double x = accel->getXAccel();
double y = accel->getYAccel();
double z = accel->getZAccel();
printf("%i - %f - %f - %f\n", Utils::millis(), x, y, z);
seismoLastMs = Utils::millis();
}
}
#pragma clang diagnostic pop
} else {
signal(SIGSEGV, crashHandler);
}
#endif
#ifndef NOWATCHDOG
Watchdog::launch();
#endif
setup();
#ifdef DEBUG
HTTPClient::sendCrashReports();
#endif
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-noreturn"
while (1) {
loop();
#ifndef GALILEO_GEN
Utils::delay(50);
#endif
}
#pragma clang diagnostic pop
return EXIT_SUCCESS;
}
void setup() {
logRotationMs = Utils::millis();
LED::init(LED_GREEN_PIN, LED_YELLOW_PIN, LED_RED_PIN);
LED::setLedAnimation(true);
Log::setLogFile(DEFAULT_LOG_PATH);
#ifdef DEBUG
Log::enableStdoutDebug(true);
Log::setLogLevel(LEVEL_DEBUG);
#endif
Log::i("Starting.........");
// If no MAC Address detect we presume that ethernet interface is down, so we'll reboot
std::string macAddress;
int i = 0;
do {
macAddress = Utils::getInterfaceMAC();
if (i >= 20) {
Log::e("MAC Address primitive failed and timeout, rebooting");
platformReboot();
}
if (macAddress.empty()) {
Log::e("MAC Address primitive failed, retrying");
Utils::delay(1000 * 3);
i++;
}
} while (macAddress.empty());
Log::i("Loading config");
// Load saved config - if not available, load defaults
Config::init();
Config::printConfig();
Log::i("Network init");
// Network init
NetworkManager::init();
if (!Config::hasMACAddress()) {
Log::i("Using default MAC Address: %s", macAddress.c_str());
Config::setMacAddress(macAddress);
} else {
Log::i("Configured MAC Address: %s", Config::getMacAddress().c_str());
}
Log::i("Init seismometer");
seismometer = Seismometer::getInstance();
seismometer->init();
Log::i("Check new config");
// Download new config from server
while (!Config::checkServerConfig()) {
Log::e("Error checking server config");
Utils::delay(5 * 1000);
}
Log::i("Update logging settings from config");
// Re-init logging from config
Log::updateFromConfig();
Log::i("NTP sync");
// NTP SYNC with NTP server
NTP::init();
NTP::sync();
Log::i("Starting UDP local command interface");
CommandInterface::commandInterfaceInit();
if (!Config::hasPosition()) {
Log::i("Getting position information");
// Wait for location from App if not avail
Log::i("Position not available, waiting for position from App");
LED::setLedAnimation(false);
LED::setLedBlinking(LED_YELLOW_PIN);
do {
#ifndef NOWATCHDOG
Watchdog::heartBeat();
#endif
CommandInterface::checkCommandPacket();
Utils::delay(200);
} while (!Config::hasPosition());
Config::printConfig();
LED::clearLedBlinking(LED_YELLOW_PIN);
LED::setLedAnimation(true);
} else {
Log::i("GPS coords: %f %f", Config::getLatitude(), Config::getLongitude());
}
Log::d("Free RAM: %lu", Utils::getFreeRam());
Log::d("INIZIALIZATION COMPLETE!");
LED::setLedAnimation(false);
LED::startupBlink();
LED::green(true);
}
void loop() {
LED::tick();
#ifndef NOWATCHDOG
Watchdog::heartBeat();
#endif
CommandInterface::checkCommandPacket();
if (Utils::millis() - netLastMs >= CHECK_NETWORK_INTERVAL) {
// If no MAC Address detect we presume that ethernet interface is down, so we'll reboot
std::string macAddress = Utils::getInterfaceMAC();
if (macAddress.empty()) {
platformReboot();
}
LED::yellow(!NetworkManager::isConnectedToInternet(true));
netLastMs = Utils::millis();
}
if (Utils::millis() - cfgLastMs >= CHECK_CONFIG_INTERVAL) {
Config::checkServerConfig();
cfgLastMs = Utils::millis();
}
if (Utils::millis() - ntpLastMs >= NTP_SYNC_INTERVAL) {
while (!NTP::sync());
ntpLastMs = Utils::millis();
}
if (Utils::millis() - seismoLastMs >= SEISMOMETER_TICK_INTERVAL) {
seismometer->tick();
seismoLastMs = Utils::millis();
}
if (Utils::millis() - logRotationMs >= 1000 * 60 * 60 * 24) {
Log::rotate();
}
#ifdef DEBUG
if (valgrindMs > 0 && Utils::millis() - valgrindMs > 1000 * 60 * 1) {
exit(EXIT_SUCCESS);
}
#endif
}
#endif