RocketLogger 2.1.3
rocketloggerd.c
Go to the documentation of this file.
1
32#include <errno.h>
33#include <stdint.h>
34#include <stdlib.h>
35#include <string.h>
36#include <time.h>
37
38#include <signal.h>
39#include <sys/reboot.h>
40#include <unistd.h>
41
42#include "gpio.h"
43#include "log.h"
44#include "rl.h"
45#include "rl_lib.h"
46
48#define RL_DAEMON_MIN_INTERVAL 1
49
51#define RL_CALIBRATION_DURATION_SEC 1
52
54#define RL_POWERUP_DELAY_US 5000
55
57#define RL_BUTTON_LONG_PRESS_SEC 3
58
60#define RL_BUTTON_VERY_LONG_PRESS_SEC 6
61
63#define RL_BUTTON_EXTRA_LONG_PRESS_SEC 10
64
73
78
79
81static char const *const log_filename = RL_DAEMON_LOG_FILE;
82
84volatile bool daemon_shutdown = false;
85
88
91
94
105int adc_calibrate(uint64_t duration) {
106 if (duration == 0) {
107 errno = EINVAL;
108 return -1;
109 }
110
111 // configure run with minimal data output
112 static rl_config_t rl_config_calibration;
113 rl_config_reset(&rl_config_calibration);
114 rl_config_calibration.background_enable = false;
115 rl_config_calibration.interactive_enable = false;
116 rl_config_calibration.web_enable = false;
117 rl_config_calibration.file_enable = false;
118 rl_config_calibration.sample_rate = RL_SAMPLE_RATE_MIN;
119 rl_config_calibration.sample_limit = RL_SAMPLE_RATE_MIN * duration;
120
121 // perform calibration run
122 int res = rl_run(&rl_config_calibration);
123
124 // reset sampling status counters
130
131 return res;
132}
133
140 static time_t timestamp_down = -1;
141 time_t timestamp = time(NULL);
142
143 // capture timestamp on button press
144 if (value == 0) {
145 timestamp_down = timestamp;
146 }
147 // process button action on button release
148 if (value == 1) {
149 // get duration and reset timestamp down
150 time_t duration = timestamp - timestamp_down;
151 timestamp_down = -1;
152
153 // skip further processing on invalid timestamp
154 if (duration > timestamp) {
155 return;
156 }
157
158 // get RocketLogger status
159 rl_status_t status;
160 int ret = rl_status_read(&status);
161 if (ret < 0) {
162 rl_log(RL_LOG_ERROR, "Failed reading status; %d message: %s", errno,
163 strerror(errno));
164 }
165
166 if (duration >= RL_BUTTON_EXTRA_LONG_PRESS_SEC) {
168 "Registered extra long press, requesting system shutdown.");
169 daemon_shutdown = true;
171 if (!status.sampling) {
172 return;
173 }
174 } else if (duration >= RL_BUTTON_VERY_LONG_PRESS_SEC) {
176 "Registered very long press, requesting system reboot.");
177 daemon_shutdown = true;
179 if (!status.sampling) {
180 return;
181 }
182 } else if (duration >= RL_BUTTON_LONG_PRESS_SEC) {
184 "Registered long press, requesting daemon restart.");
185 daemon_shutdown = true;
187 if (!status.sampling) {
188 return;
189 }
190 }
191
192 char *cmd[3] = {"rocketlogger", NULL, NULL};
193 if (status.sampling) {
194 cmd[1] = "stop";
195 } else {
196 cmd[1] = "start";
197 }
198
199 // create child process to start RocketLogger
200 pid_t pid = fork();
201 if (pid < 0) {
202 rl_log(RL_LOG_ERROR, "Failed forking process; %d message: %s",
203 errno, strerror(errno));
204 }
205 if (pid == 0) {
206 // in child process, execute RocketLogger
207 execvp(cmd[0], cmd);
209 "Failed executing `rocketlogger %s`; %d message: %s", cmd,
210 errno, strerror(errno));
211 } else {
212 // in parent process log pid
213 rl_log(RL_LOG_INFO, "Started RocketLogger with pid=%d.", pid);
214 }
215 }
216 // interrupt rate control
218}
219
225static void signal_handler(int signal_number) {
226 // signal to terminate the daemon (systemd stop)
227 if (signal_number == SIGTERM) {
228 signal(signal_number, SIG_IGN);
229 rl_log(RL_LOG_INFO, "Received SIGTERM, shutting down daemon.");
230 daemon_shutdown = true;
231 }
232}
233
241int main(void) {
242 int ret = SUCCESS;
243
244 // init log module
245 rl_log_init(log_filename, RL_LOG_VERBOSE);
246
247 // set effective user ID of the process
248 ret = setuid(0);
249 if (ret < 0) {
250 rl_log(RL_LOG_ERROR, "Failed setting effective user ID; %d message: %s",
251 errno, strerror(errno));
252 exit(EXIT_FAILURE);
253 }
254
255 rl_log(RL_LOG_VERBOSE, "running with real user ID: %d", getuid());
256 rl_log(RL_LOG_VERBOSE, "running with effective user ID: %d", geteuid());
257 rl_log(RL_LOG_VERBOSE, "running with real group ID: %d", getgid());
258 rl_log(RL_LOG_VERBOSE, "running with effective group ID: %d", getegid());
259
260 // initialize GPIO module
261 gpio_init();
262
263 // hardware initialization
265 if (gpio_power == NULL) {
266 rl_log(RL_LOG_ERROR, "Failed configuring power switch; %d message: %s",
267 errno, strerror(errno));
268 exit(EXIT_FAILURE);
269 }
270 ret = gpio_set_value(gpio_power, 1);
271 if (ret < 0) {
272 rl_log(RL_LOG_ERROR, "Failed powering up cape; %d message: %s", errno,
273 strerror(errno));
274 exit(EXIT_FAILURE);
275 }
276
277 // wait for converter soft start (> 1 ms)
278 usleep(RL_POWERUP_DELAY_US);
279
282 if (gpio_button == NULL) {
283 rl_log(RL_LOG_ERROR, "Failed configuring button; %d message: %s", errno,
284 strerror(errno));
285 exit(EXIT_FAILURE);
286 }
287
288 // create shared memory for state
289 ret = rl_status_shm_init();
290 if (ret < 0) {
291 rl_log(RL_LOG_ERROR, "Failed initializing status shared memory.");
292 exit(EXIT_FAILURE);
293 }
294
295 // register signal handler for SIGTERM (for stopping daemon)
296 struct sigaction signal_action;
297 signal_action.sa_handler = signal_handler;
298 sigemptyset(&signal_action.sa_mask);
299 signal_action.sa_flags = 0;
300
301 ret = sigaction(SIGTERM, &signal_action, NULL);
302 if (ret < 0) {
304 "can't register signal handler for SIGTERM; %d message: %s",
305 errno, strerror(errno));
306 exit(EXIT_FAILURE);
307 }
308
309 // calibrate ADC reference voltage
310 rl_log(RL_LOG_INFO, "Performing ADC reference calibration.");
312
313 // check error status
314 rl_status_t status;
315 rl_status_read(&status);
316 if (status.error) {
317 rl_log(RL_LOG_ERROR, "ADC reference calibration failed, terminating.");
318 } else {
319 // daemon main loop
320 rl_log(RL_LOG_INFO, "RocketLogger daemon running.");
321
322 daemon_shutdown = false;
323 while (!daemon_shutdown) {
324 // wait for interrupt with infinite timeout
325 int value = gpio_wait_interrupt(gpio_button, NULL);
327 }
328
329 rl_log(RL_LOG_INFO, "RocketLogger daemon stopped.");
330 }
331
332 rl_status_read(&status);
333
334 // remove shared memory for state
336
337 // deinitialize and shutdown hardware
341 gpio_deinit();
342
343 // perform requested system action
345 rl_log(RL_LOG_INFO, "Rebooting system.");
346 sync();
347 reboot(RB_AUTOBOOT);
349 rl_log(RL_LOG_INFO, "Powering off system.");
350 sync();
351 reboot(RB_POWER_OFF);
352 }
353
354 if (status.error) {
355 exit(EXIT_FAILURE);
356 }
357 exit(EXIT_SUCCESS);
358}
int gpio_set_value(gpio_t *gpio, int value)
Definition gpio.c:135
int gpio_init()
Definition gpio.c:77
void gpio_release(gpio_t *gpio)
Definition gpio.c:130
void gpio_deinit()
Definition gpio.c:92
int gpio_wait_interrupt(gpio_t *gpio, const struct timespec *timeout)
Definition gpio.c:187
gpio_t * gpio_setup_interrupt(int gpio_number, gpio_interrupt_t edge, const char *name)
Definition gpio.c:148
gpio_t * gpio_setup(int gpio_number, gpio_mode_t mode, const char *name)
Definition gpio.c:103
#define GPIO_POWER
GPIO number of RocketLogger cape power enable.
Definition gpio.h:49
@ GPIO_INTERRUPT_BOTH
Interrupt on both edges.
Definition gpio.h:66
@ GPIO_MODE_OUT
GPIO write mode.
Definition gpio.h:56
struct gpiod_line gpio_t
Definition gpio.h:72
#define GPIO_BUTTON
GPIO number of start/stop button.
Definition gpio.h:47
int rl_log(rl_log_level_t log_level, char const *const format,...)
Definition log.c:82
int rl_log_init(char const *const log_file, rl_log_level_t verbosity)
Definition log.c:49
@ RL_LOG_ERROR
Error.
Definition log.h:49
@ RL_LOG_VERBOSE
Verbose.
Definition log.h:52
@ RL_LOG_INFO
Information.
Definition log.h:51
int rl_status_write(rl_status_t *const status)
Definition rl.c:641
void rl_config_reset(rl_config_t *const config)
Definition rl.c:360
int rl_status_read(rl_status_t *const status)
Definition rl.c:602
int rl_status_shm_init(void)
Definition rl.c:565
int rl_status_shm_deinit(void)
Definition rl.c:579
rl_status_t rl_status
Global RocketLogger status variable.
Definition rl.c:112
#define RL_SAMPLE_RATE_MIN
Minimum native sample rate of the ADC in samples per second.
Definition rl.h:62
#define SUCCESS
Function return value for successful completion.
Definition rl.h:44
#define RL_DAEMON_LOG_FILE
RocketLogger daemon log file.
Definition rl.h:51
int rl_run(rl_config_t *const config)
Definition rl_lib.c:100
gpio_t * gpio_power
GPIO handle for power switch.
#define RL_POWERUP_DELAY_US
Delay on cape power up (in microseconds)
#define RL_BUTTON_VERY_LONG_PRESS_SEC
Min duration of a very long button press (in seconds)
int main(void)
#define RL_BUTTON_LONG_PRESS_SEC
Min duration of a long button press (in seconds)
volatile bool daemon_shutdown
Flag to terminate the infinite daemon loop.
enum system_action system_action_t
void button_interrupt_handler(int value)
#define RL_DAEMON_MIN_INTERVAL
Minimal time interval between two interrupts (in seconds)
gpio_t * gpio_button
GPIO handle for user button.
int adc_calibrate(uint64_t duration)
system_action
@ SYSTEM_ACTION_POWEROFF
power off the system
@ SYSTEM_ACTION_REBOOT
reboot the system
@ SYSTEM_ACTION_NONE
perform no system action
#define RL_CALIBRATION_DURATION_SEC
Duration of calibration run (in seconds)
#define RL_BUTTON_EXTRA_LONG_PRESS_SEC
Min duration of an extra long button press (in seconds)
bool interactive_enable
Display measurement data interactively in CLI while sampling.
Definition rl.h:160
bool background_enable
Put the measurement process in background after successful start.
Definition rl.h:158
uint64_t sample_limit
Sample limit (0 for continuous)
Definition rl.h:162
bool web_enable
Enable web interface connection.
Definition rl.h:176
uint32_t sample_rate
Sampling rate.
Definition rl.h:164
bool file_enable
Enable storing measurements to file.
Definition rl.h:182
uint64_t buffer_count
Number of buffers taken.
Definition rl.h:209
bool error
Whether the logger is in an error state.
Definition rl.h:205
bool sampling
Sampling state, true: sampling, false: idle.
Definition rl.h:203
uint64_t sample_count
Number of samples taken.
Definition rl.h:207