Line data Source code
1 : #pragma once
2 :
3 : #include "AP_Logger_config.h"
4 :
5 : #if HAL_LOGGING_ENABLED
6 :
7 : #include <AP_Common/Bitmask.h>
8 : #include <AP_Param/AP_Param.h>
9 : #include <GCS_MAVLink/GCS_MAVLink.h>
10 : #include <AP_Mission/AP_Mission.h>
11 : #include <AP_Vehicle/ModeReason.h>
12 : #include "LogStructure.h"
13 :
14 : class LoggerMessageWriter_DFLogStart;
15 :
16 : // class to handle rate limiting of log messages
17 : class AP_Logger_RateLimiter
18 : {
19 : public:
20 : AP_Logger_RateLimiter(const class AP_Logger &_front, const AP_Float &_limit_hz, const AP_Float &_disarm_limit_hz);
21 :
22 : // return true if message passes the rate limit test
23 : bool should_log(uint8_t msgid, bool writev_streaming);
24 : bool should_log_streaming(uint8_t msgid, float rate_hz);
25 :
26 : private:
27 : const AP_Logger &front;
28 : const AP_Float &rate_limit_hz;
29 : const AP_Float &disarm_rate_limit_hz;
30 :
31 : // time in ms we last sent this message
32 : uint16_t last_send_ms[256];
33 :
34 : // the last scheduler counter when we sent a msg. this allows us
35 : // to detect when we are sending a multi-instance message
36 : uint16_t last_sched_count[256];
37 :
38 : // mask of message types that are not streaming. This is a cache
39 : // to avoid costly calls to structure_for_msg_type
40 : Bitmask<256> not_streaming;
41 :
42 : // result of last decision for a message. Used for multi-instance
43 : // handling
44 : Bitmask<256> last_return;
45 : };
46 :
47 : class AP_Logger_Backend
48 : {
49 :
50 : public:
51 : FUNCTOR_TYPEDEF(vehicle_startup_message_Writer, void);
52 :
53 : AP_Logger_Backend(AP_Logger &front,
54 : class LoggerMessageWriter_DFLogStart *writer);
55 :
56 : vehicle_startup_message_Writer vehicle_message_writer() const;
57 :
58 : virtual bool CardInserted(void) const = 0;
59 :
60 : // erase handling
61 : virtual void EraseAll() = 0;
62 :
63 : /* Write a block of data at current offset */
64 173548673 : bool WriteBlock(const void *pBuffer, uint16_t size) {
65 173548673 : return WritePrioritisedBlock(pBuffer, size, false);
66 : }
67 :
68 7176441 : bool WriteCriticalBlock(const void *pBuffer, uint16_t size) {
69 7176441 : return WritePrioritisedBlock(pBuffer, size, true);
70 : }
71 :
72 : bool WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical, bool writev_streaming=false);
73 :
74 : // high level interface, indexed by the position in the list of logs
75 : virtual uint16_t find_last_log() = 0;
76 : virtual void get_log_boundaries(uint16_t list_entry, uint32_t & start_page, uint32_t & end_page) = 0;
77 : virtual void get_log_info(uint16_t list_entry, uint32_t &size, uint32_t &time_utc) = 0;
78 : virtual int16_t get_log_data(uint16_t list_entry, uint16_t page, uint32_t offset, uint16_t len, uint8_t *data) = 0;
79 : virtual void end_log_transfer() = 0;
80 : virtual uint16_t get_num_logs() = 0;
81 : virtual uint16_t find_oldest_log();
82 :
83 : virtual bool logging_started(void) const = 0;
84 :
85 : virtual void Init() = 0;
86 :
87 : virtual uint32_t bufferspace_available() = 0;
88 :
89 : virtual void PrepForArming();
90 :
91 0 : virtual void start_new_log() { }
92 :
93 : /* stop logging - close output files etc etc.
94 : *
95 : * note that this doesn't stop logging from starting up again
96 : * immediately - e.g. AP_Logger_MAVLink might get another start
97 : * packet from a client.
98 : */
99 : virtual void stop_logging(void) = 0;
100 : // asynchronously stop logging, status can be determined through logging_started()
101 15 : virtual void stop_logging_async(void) { stop_logging(); }
102 :
103 : void Fill_Format(const struct LogStructure *structure, struct log_Format &pkt);
104 : void Fill_Format_Units(const struct LogStructure *s, struct log_Format_Units &pkt);
105 :
106 : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX
107 : // currently only AP_Logger_File support this:
108 0 : virtual void flush(void) { }
109 : #endif
110 :
111 : // for Logger_MAVlink
112 0 : virtual void remote_log_block_status_msg(const class GCS_MAVLINK &link,
113 0 : const mavlink_message_t &msg) { }
114 : // end for Logger_MAVlink
115 :
116 : virtual void periodic_tasks();
117 :
118 : uint8_t num_types() const;
119 : const struct LogStructure *structure(uint8_t structure) const;
120 :
121 : uint8_t num_units() const;
122 : const struct UnitStructure *unit(uint8_t unit) const;
123 :
124 : uint8_t num_multipliers() const;
125 : const struct MultiplierStructure *multiplier(uint8_t multiplier) const;
126 :
127 : bool Write_RTC();
128 :
129 : bool Write_EntireMission();
130 : bool Write_RallyPoint(uint8_t total,
131 : uint8_t sequence,
132 : const class RallyLocation &rally_point);
133 : bool Write_Rally();
134 : #if HAL_LOGGER_FENCE_ENABLED
135 : bool Write_FencePoint(uint8_t total, uint8_t sequence, const class AC_PolyFenceItem &fence_point);
136 : bool Write_Fence();
137 : #endif
138 : bool Write_Format(const struct LogStructure *structure);
139 101302690 : bool have_emitted_format_for_type(LogMessages a_type) const {
140 101302690 : return _formats_written.get(uint8_t(a_type));
141 : }
142 : bool Write_Message(const char *message);
143 : bool Write_MessageF(const char *fmt, ...);
144 : bool Write_MessageChunk(uint8_t id, const char *messagechunk, uint8_t chunk_seq);
145 : bool Write_Mission_Cmd(const AP_Mission &mission,
146 : const AP_Mission::Mission_Command &cmd,
147 : LogMessages id);
148 : bool Write_Mode(uint8_t mode, const ModeReason reason);
149 : bool Write_Parameter(const char *name, float value, float default_val);
150 : bool Write_Parameter(const AP_Param *ap,
151 : const AP_Param::ParamToken &token,
152 : enum ap_var_type type,
153 : float default_val);
154 : bool Write_VER();
155 :
156 1116947 : uint32_t num_dropped(void) const {
157 1116947 : return _dropped;
158 : }
159 :
160 : /*
161 : * Write support
162 : */
163 : // write a FMT message out (if it hasn't been done already).
164 : // Returns true if the FMT message has ever been written.
165 : bool Write_Emit_FMT(uint8_t msg_type);
166 :
167 : // output a FMT message if not already done so
168 : void Safe_Write_Emit_FMT(uint8_t msg_type);
169 :
170 : // write a log message out to the log of msg_type type, with
171 : // values contained in arg_list:
172 : bool Write(uint8_t msg_type, va_list arg_list, bool is_critical=false, bool is_streaming=false);
173 :
174 : // these methods are used for mavlink system status and arming checks
175 : virtual bool logging_enabled() const;
176 : virtual bool logging_failed() const = 0;
177 :
178 : // We may need to make sure data is loggable before starting the
179 : // EKF; when allow_start_ekf we should be able to log that data
180 : bool allow_start_ekf() const;
181 :
182 : virtual void vehicle_was_disarmed();
183 :
184 : bool Write_Unit(const struct UnitStructure *s);
185 : bool Write_Multiplier(const struct MultiplierStructure *s);
186 : bool Write_Format_Units(const struct LogStructure *structure);
187 :
188 23835 : virtual void io_timer(void) {}
189 :
190 : protected:
191 :
192 : AP_Logger &_front;
193 :
194 : virtual void periodic_10Hz(const uint32_t now);
195 : virtual void periodic_1Hz();
196 : virtual void periodic_fullrate();
197 :
198 : bool ShouldLog(bool is_critical);
199 : virtual bool WritesOK() const = 0;
200 : virtual bool StartNewLogOK() const;
201 :
202 : // called by PrepForArming to actually start logging
203 5 : virtual void PrepForArming_start_logging(void) {
204 5 : start_new_log();
205 5 : }
206 :
207 : /*
208 : read a block
209 : */
210 : virtual void WriteMoreStartupMessages();
211 : virtual void push_log_blocks();
212 :
213 : LoggerMessageWriter_DFLogStart *_startup_messagewriter;
214 : bool _writing_startup_messages;
215 :
216 : uint16_t _cached_oldest_log;
217 :
218 : uint32_t _dropped;
219 : // should we rotate when we next stop logging
220 : bool _rotate_pending;
221 :
222 : // must be called when a new log is being started:
223 : virtual void start_new_log_reset_variables();
224 : // convert between log numbering in storage and normalized numbering
225 : uint16_t log_num_from_list_entry(const uint16_t list_entry);
226 :
227 178188677 : uint32_t critical_message_reserved_space(uint32_t bufsize) const {
228 : // possibly make this a proportional to buffer size?
229 178188677 : uint32_t ret = 1024;
230 178188677 : if (ret > bufsize) {
231 : // in this case you will only get critical messages
232 0 : ret = bufsize;
233 : }
234 178188677 : return ret;
235 : };
236 3454259 : uint32_t non_messagewriter_message_reserved_space(uint32_t bufsize) const {
237 : // possibly make this a proportional to buffer size?
238 3454259 : uint32_t ret = 4096;
239 3454259 : if (ret >= bufsize) {
240 : // need to allow messages out from the messagewriters. In
241 : // this case while you have a messagewriter you won't get
242 : // any other messages. This should be a corner case!
243 0 : ret = 0;
244 : }
245 3454259 : return ret;
246 : };
247 :
248 : virtual bool _WritePrioritisedBlock(const void *pBuffer, uint16_t size, bool is_critical) = 0;
249 :
250 : bool _initialised;
251 :
252 : void df_stats_gather(uint16_t bytes_written, uint32_t space_remaining);
253 : void df_stats_log();
254 : void df_stats_clear();
255 :
256 : AP_Logger_RateLimiter *rate_limiter;
257 :
258 : private:
259 : // statistics support
260 : struct df_stats {
261 : uint16_t blocks;
262 : uint32_t bytes;
263 : uint32_t buf_space_min;
264 : uint32_t buf_space_max;
265 : uint32_t buf_space_sigma;
266 : };
267 : struct df_stats stats;
268 :
269 : uint32_t _last_periodic_1Hz;
270 : uint32_t _last_periodic_10Hz;
271 : bool have_logged_armed;
272 :
273 : void Write_AP_Logger_Stats_File(const struct df_stats &_stats);
274 : void validate_WritePrioritisedBlock(const void *pBuffer, uint16_t size);
275 :
276 : bool message_type_from_block(const void *pBuffer, uint16_t size, LogMessages &type) const;
277 : bool ensure_format_emitted(const void *pBuffer, uint16_t size);
278 : bool emit_format_for_type(LogMessages a_type);
279 : Bitmask<256> _formats_written;
280 :
281 : uint8_t msg_id; // the ID of the next MSG message that will be logged
282 : };
283 :
284 : #endif // HAL_LOGGING_ENABLED
|