Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
preflight_checks.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2022 Freek van Tienen <freek.v.tienen@gmail.com>
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
27 #include "preflight_checks.h"
29 #include <stdio.h>
30 
32 #ifndef PREFLIGHT_CHECK_MAX_MSGBUF
33 #define PREFLIGHT_CHECK_MAX_MSGBUF 1024
34 #endif
35 
37 #ifndef PREFLIGHT_CHECK_SEPERATOR
38 #define PREFLIGHT_CHECK_SEPERATOR ';'
39 #endif
40 
42 #ifndef PREFLIGHT_CHECK_INFO_TIMEOUT
43 #define PREFLIGHT_CHECK_INFO_TIMEOUT 5
44 #endif
45 
46 static struct preflight_check_t *preflight_head = NULL;
48 
56 {
57  // Prepend the preflight check
59  preflight_head = check;
60  check->func = func;
61  check->next = next;
62 }
63 
70 bool preflight_check(void)
71 {
72  static float last_info_time = 0;
73  char error_msg[PREFLIGHT_CHECK_MAX_MSGBUF];
74  struct preflight_result_t result = {
75  .message = error_msg,
76  .max_len = PREFLIGHT_CHECK_MAX_MSGBUF,
77  .fail_cnt = 0,
78  .warning_cnt = 0,
79  .success_cnt = 0
80  };
81 
82  // Go through all the checks
83  struct preflight_check_t *check = preflight_head;
84  while (check != NULL) {
85  // Peform the check and register errors
86  check->func(&result);
87  check = check->next;
88  }
89 
90  // We failed a check or have a warning
91  if (result.fail_cnt > 0 || result.warning_cnt > 0) {
92  // Only send every xx amount of seconds
93  if ((get_sys_time_float() - last_info_time) > PREFLIGHT_CHECK_INFO_TIMEOUT) {
94  // Record the total
95  int rc = 0;
96  if (result.fail_cnt > 0) {
97  rc = snprintf(result.message, result.max_len, "*Preflight fail [fail:%d warn:%d tot:%d]*", result.fail_cnt,
98  result.warning_cnt, (result.fail_cnt + result.warning_cnt + result.success_cnt));
99  } else {
100  rc = snprintf(result.message, result.max_len, "*Preflight success with warnings [%d/%d]*", result.warning_cnt,
101  (result.fail_cnt + result.warning_cnt + result.success_cnt));
102  }
103  if (rc > 0) {
104  result.max_len -= rc;
105  }
106 
107  // Send the errors seperatly
108  uint16_t last_sendi = 0;
109  for (uint16_t i = 0; i <= PREFLIGHT_CHECK_MAX_MSGBUF - result.max_len; i++) {
110  if (error_msg[i] == PREFLIGHT_CHECK_SEPERATOR || i == (PREFLIGHT_CHECK_MAX_MSGBUF - result.max_len)) {
111  DOWNLINK_SEND_INFO_MSG(DefaultChannel, DefaultDevice, i - last_sendi, &error_msg[last_sendi]);
112  last_sendi = i + 1;
113  }
114  }
115 
116  // Update the time
117  last_info_time = get_sys_time_float();
118  }
119 
120  // Only if we fail a check
121  if (result.fail_cnt > 0) {
122  return false;
123  } else {
124  return true;
125  }
126  }
127 
128  // Send success down
129  int rc = snprintf(error_msg, PREFLIGHT_CHECK_MAX_MSGBUF, "Preflight success [%d]", result.success_cnt);
130  if (rc > 0) {
131  DOWNLINK_SEND_INFO_MSG(DefaultChannel, DefaultDevice, rc, error_msg);
132  }
133 
134  // Return success if we didn't fail a preflight check
135  return true;
136 }
137 
145 void preflight_error(struct preflight_result_t *result, const char *fmt, ...)
146 {
147  // Record the error count
148  result->fail_cnt++;
149 
150  // No more space in the message
151  if (result->max_len <= 0) {
152  return;
153  }
154 
155  // Add the error
156  va_list args;
157  va_start(args, fmt);
158  int rc = vsnprintf(result->message, result->max_len, fmt, args);
159  va_end(args);
160 
161  // Remove the length from the buffer if it was successfull
162  if (rc > 0) {
163  result->max_len -= rc;
164  result->message += rc;
165 
166  // Add seperator if it fits
167  if (result->max_len > 0) {
168  result->message[0] = PREFLIGHT_CHECK_SEPERATOR;
169  result->max_len--;
170  result->message++;
171 
172  // Add the '\0' character
173  if (result->max_len > 0) {
174  result->message[0] = 0;
175  }
176  }
177  }
178 }
179 
187 void preflight_warning(struct preflight_result_t *result, const char *fmt, ...)
188 {
189  // Record the warning count
190  result->warning_cnt++;
191 
192  // No more space in the message
193  if (result->max_len <= 0) {
194  return;
195  }
196 
197  // Add the warning to the error string
198  va_list args;
199  va_start(args, fmt);
200  int rc = vsnprintf(result->message, result->max_len, fmt, args);
201  va_end(args);
202 
203  // Remove the length from the buffer if it was successfull
204  if (rc > 0) {
205  result->max_len -= rc;
206  result->message += rc;
207 
208  // Add seperator if it fits
209  if (result->max_len > 0) {
210  result->message[0] = PREFLIGHT_CHECK_SEPERATOR;
211  result->max_len--;
212  result->message++;
213 
214  // Add the '\0' character
215  if (result->max_len > 0) {
216  result->message[0] = 0;
217  }
218  }
219  }
220 }
221 
229 void preflight_success(struct preflight_result_t *result, const char *fmt __attribute__((unused)), ...)
230 {
231  // Record the success count
232  result->success_cnt++;
233 }
#define PREFLIGHT_CHECK_INFO_TIMEOUT
Only send messages down every xx amount of seconds.
void preflight_error(struct preflight_result_t *result, const char *fmt,...)
Register a preflight error used inside the preflight checking functions.
void preflight_success(struct preflight_result_t *result, const char *fmt,...)
Register a preflight success used inside the preflight checking functions.
bool preflight_bypass
static struct preflight_check_t * preflight_head
#define PREFLIGHT_CHECK_SEPERATOR
Seperating character for storing the errors.
void preflight_warning(struct preflight_result_t *result, const char *fmt,...)
Register a preflight error used inside the preflight checking functions.
bool preflight_check(void)
Perform all the preflight checks.
void preflight_check_register(struct preflight_check_t *check, preflight_check_f func)
Register a preflight check and add it to the linked list.
#define PREFLIGHT_CHECK_MAX_MSGBUF
Maximum combined message size for storing the errors.
preflight_check_f func
void(* preflight_check_f)(struct preflight_result_t *result)
struct preflight_check_t * next
#define FALSE
Definition: std.h:5
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition: sys_time.h:138
Periodic telemetry system header (includes downlink utility and generated code).
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
Definition: vl53l1_types.h:88