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"
30 #include <stdio.h>
31 
33 #ifndef PREFLIGHT_CHECK_MAX_MSGBUF
34 #define PREFLIGHT_CHECK_MAX_MSGBUF 1024
35 #endif
36 
38 #ifndef PREFLIGHT_CHECK_SEPERATOR
39 #define PREFLIGHT_CHECK_SEPERATOR ';'
40 #endif
41 
43 #ifndef PREFLIGHT_CHECK_INFO_TIMEOUT
44 #define PREFLIGHT_CHECK_INFO_TIMEOUT 5
45 #endif
46 
48 #ifndef PREFLIGHT_CHECK_GROUND
49 #define PREFLIGHT_CHECK_GROUND TRUE
50 #endif
51 
53 #ifndef PREFLIGHT_CHECK_BYPASS
54 #define PREFLIGHT_CHECK_BYPASS FALSE
55 #endif
56 
58 bool preflight_ground_done = false;
59 
60 static struct preflight_check_t *preflight_head = NULL;
61 
69 {
70  // Prepend the preflight check
72  preflight_head = check;
73  check->func = func;
74  check->next = next;
75 }
76 
83 bool preflight_check(void)
84 {
85  static float last_info_time = 0;
86  char error_msg[PREFLIGHT_CHECK_MAX_MSGBUF];
87  struct preflight_result_t result = {
88  .message = error_msg,
89  .max_len = PREFLIGHT_CHECK_MAX_MSGBUF,
90  .fail_cnt = 0,
91  .warning_cnt = 0,
92  .success_cnt = 0
93  };
94 
95  // Go through all the checks
96  struct preflight_check_t *check = preflight_head;
97  while (check != NULL) {
98  // Peform the check and register errors
99  check->func(&result);
100  check = check->next;
101  }
102 
103  // Add the ground check
104 #if PREFLIGHT_CHECK_GROUND
105  if (!preflight_ground_done) {
106  preflight_error(&result, "Ground checks not done");
107  } else {
108  preflight_success(&result, "Ground checks done");
109  }
110 #endif
111 
112  // We failed a check or have a warning
113  if (result.fail_cnt > 0 || result.warning_cnt > 0) {
114  // Only send every xx amount of seconds
115  if ((get_sys_time_float() - last_info_time) > PREFLIGHT_CHECK_INFO_TIMEOUT) {
116  // Record the total
117  int rc = 0;
118  if (result.fail_cnt > 0) {
119  rc = snprintf(result.message, result.max_len, "*Preflight fail [fail:%d warn:%d tot:%d]*", result.fail_cnt,
120  result.warning_cnt, (result.fail_cnt + result.warning_cnt + result.success_cnt));
121  } else {
122  rc = snprintf(result.message, result.max_len, "*Preflight success with warnings [%d/%d]*", result.warning_cnt,
123  (result.fail_cnt + result.warning_cnt + result.success_cnt));
124  }
125  if (rc > 0) {
126  result.max_len -= rc;
127  }
128 
129  // Send the errors seperatly
130  uint16_t last_sendi = 0;
131  for (uint16_t i = 0; i <= PREFLIGHT_CHECK_MAX_MSGBUF - result.max_len; i++) {
132  if (error_msg[i] == PREFLIGHT_CHECK_SEPERATOR || i == (PREFLIGHT_CHECK_MAX_MSGBUF - result.max_len)) {
133  DOWNLINK_SEND_INFO_MSG(DefaultChannel, DefaultDevice, i - last_sendi, &error_msg[last_sendi]);
134 #if FLIGHTRECORDER_SDLOG
135  pprz_msg_send_INFO_MSG(&pprzlog_tp.trans_tx, &flightrecorder_sdlog.device, AC_ID, i - last_sendi, &error_msg[last_sendi]);
136 #endif
137  last_sendi = i + 1;
138  }
139  }
140 
141  // Update the time
142  last_info_time = get_sys_time_float();
143  }
144 
145  // Only if we fail a check
146  if (result.fail_cnt > 0) {
147  return false;
148  } else {
149  return true;
150  }
151  }
152 
153  // Send success down
154  int rc = snprintf(error_msg, PREFLIGHT_CHECK_MAX_MSGBUF, "*Preflight success [%d]*", result.success_cnt);
155  if (rc > 0) {
156  DOWNLINK_SEND_INFO_MSG(DefaultChannel, DefaultDevice, rc, error_msg);
157 #if FLIGHTRECORDER_SDLOG
158  pprz_msg_send_INFO_MSG(&pprzlog_tp.trans_tx, &flightrecorder_sdlog.device, AC_ID, strlen(error_msg), error_msg);
159 #endif
160  }
161 
162  // Return success if we didn't fail a preflight check
163  return true;
164 }
165 
173 void preflight_error(struct preflight_result_t *result, const char *fmt, ...)
174 {
175  // Record the error count
176  result->fail_cnt++;
177 
178  // No more space in the message
179  if (result->max_len <= 0) {
180  return;
181  }
182 
183  // Add the error
184  va_list args;
185  va_start(args, fmt);
186  int rc = vsnprintf(result->message, result->max_len, fmt, args);
187  va_end(args);
188 
189  // Remove the length from the buffer if it was successfull
190  if (rc > 0) {
191  result->max_len -= rc;
192  result->message += rc;
193 
194  // Add seperator if it fits
195  if (result->max_len > 0) {
196  result->message[0] = PREFLIGHT_CHECK_SEPERATOR;
197  result->max_len--;
198  result->message++;
199 
200  // Add the '\0' character
201  if (result->max_len > 0) {
202  result->message[0] = 0;
203  }
204  }
205  }
206 }
207 
215 void preflight_warning(struct preflight_result_t *result, const char *fmt, ...)
216 {
217  // Record the warning count
218  result->warning_cnt++;
219 
220  // No more space in the message
221  if (result->max_len <= 0) {
222  return;
223  }
224 
225  // Add the warning to the error string
226  va_list args;
227  va_start(args, fmt);
228  int rc = vsnprintf(result->message, result->max_len, fmt, args);
229  va_end(args);
230 
231  // Remove the length from the buffer if it was successfull
232  if (rc > 0) {
233  result->max_len -= rc;
234  result->message += rc;
235 
236  // Add seperator if it fits
237  if (result->max_len > 0) {
238  result->message[0] = PREFLIGHT_CHECK_SEPERATOR;
239  result->max_len--;
240  result->message++;
241 
242  // Add the '\0' character
243  if (result->max_len > 0) {
244  result->message[0] = 0;
245  }
246  }
247  }
248 }
249 
257 void preflight_success(struct preflight_result_t *result, const char *fmt __attribute__((unused)), ...)
258 {
259  // Record the success count
260  result->success_cnt++;
261 }
262 
263 void preflight_checks_log_bypass(bool bypass) {
264  char *msg = (bypass)? "*Preflight checks bypassed*" : "*Preflight checks unbypassed*";
265  int len = strlen(msg);
266 
267  DOWNLINK_SEND_INFO_MSG(DefaultChannel, DefaultDevice, len, msg);
268 #if FLIGHTRECORDER_SDLOG
269  pprz_msg_send_INFO_MSG(&pprzlog_tp.trans_tx, &flightrecorder_sdlog.device, AC_ID, len, msg);
270 #endif
271  preflight_bypass = bypass;
272 }
uint8_t msg[10]
Buffer used for general comunication over SPI (out buffer)
struct pprzlog_transport pprzlog_tp
PPRZLOG transport structure.
Definition: pprzlog_tp.c:29
#define PREFLIGHT_CHECK_INFO_TIMEOUT
Only send messages down every xx amount of seconds.
#define PREFLIGHT_CHECK_BYPASS
Bypass the preflight checks.
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
bool preflight_ground_done
void preflight_checks_log_bypass(bool 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 warning 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
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