Line data Source code
1 : /*
2 : This program is free software: you can redistribute it and/or modify
3 : it under the terms of the GNU General Public License as published by
4 : the Free Software Foundation, either version 3 of the License, or
5 : (at your option) any later version.
6 :
7 : This program is distributed in the hope that it will be useful,
8 : but WITHOUT ANY WARRANTY; without even the implied warranty of
9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 : GNU General Public License for more details.
11 :
12 : You should have received a copy of the GNU General Public License
13 : along with this program. If not, see <http://www.gnu.org/licenses/>.
14 : */
15 :
16 : #include "AP_Scripting_config.h"
17 :
18 : #if AP_SCRIPTING_ENABLED
19 :
20 : #include <AP_Scripting/AP_Scripting.h>
21 : #include <AP_RCTelemetry/AP_CRSF_Telem.h>
22 : #include <AP_HAL/AP_HAL.h>
23 : #include <GCS_MAVLink/GCS.h>
24 : #include <AP_Arming/AP_Arming.h>
25 :
26 : #include "lua_scripts.h"
27 : #include "AP_Scripting_helpers.h"
28 :
29 : // ensure that we have a set of stack sizes, and enforce constraints around it
30 : // except for the minimum size, these are allowed to be defined by the build system
31 : #undef SCRIPTING_STACK_MIN_SIZE
32 : #define SCRIPTING_STACK_MIN_SIZE (8 * 1024)
33 :
34 : #if !defined(SCRIPTING_STACK_SIZE)
35 : #define SCRIPTING_STACK_SIZE (17 * 1024) // Linux experiences stack corruption at ~16.25KB when handed bad scripts
36 : #endif // !defined(SCRIPTING_STACK_SIZE)
37 :
38 : #if !defined(SCRIPTING_STACK_MAX_SIZE)
39 : #define SCRIPTING_STACK_MAX_SIZE (64 * 1024)
40 : #endif // !defined(SCRIPTING_STACK_MAX_SIZE)
41 :
42 : #if !defined(SCRIPTING_HEAP_SIZE)
43 : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX || HAL_MEM_CLASS >= HAL_MEM_CLASS_1000
44 : #define SCRIPTING_HEAP_SIZE (200 * 1024)
45 : #elif HAL_MEM_CLASS >= HAL_MEM_CLASS_500
46 : #define SCRIPTING_HEAP_SIZE (100 * 1024)
47 : #else
48 : #define SCRIPTING_HEAP_SIZE (43 * 1024)
49 : #endif
50 : #endif // !defined(SCRIPTING_HEAP_SIZE)
51 :
52 : static_assert(SCRIPTING_STACK_SIZE >= SCRIPTING_STACK_MIN_SIZE, "Scripting requires a larger minimum stack size");
53 : static_assert(SCRIPTING_STACK_SIZE <= SCRIPTING_STACK_MAX_SIZE, "Scripting requires a smaller stack size");
54 :
55 : #ifndef SCRIPTING_ENABLE_DEFAULT
56 : #define SCRIPTING_ENABLE_DEFAULT 0
57 : #endif
58 :
59 : #if AP_NETWORKING_ENABLED
60 : #include <AP_HAL/utility/Socket.h>
61 : #endif
62 :
63 : extern const AP_HAL::HAL& hal;
64 :
65 : const AP_Param::GroupInfo AP_Scripting::var_info[] = {
66 : // @Param: ENABLE
67 : // @DisplayName: Enable Scripting
68 : // @Description: Controls if scripting is enabled
69 : // @Values: 0:None,1:Lua Scripts
70 : // @RebootRequired: True
71 : // @User: Advanced
72 : AP_GROUPINFO_FLAGS("ENABLE", 1, AP_Scripting, _enable, SCRIPTING_ENABLE_DEFAULT, AP_PARAM_FLAG_ENABLE),
73 :
74 : // @Param: VM_I_COUNT
75 : // @DisplayName: Scripting Virtual Machine Instruction Count
76 : // @Description: The number virtual machine instructions that can be run before considering a script to have taken an excessive amount of time
77 : // @Range: 1000 1000000
78 : // @Increment: 10000
79 : // @User: Advanced
80 : AP_GROUPINFO("VM_I_COUNT", 2, AP_Scripting, _script_vm_exec_count, 10000),
81 :
82 : // @Param: HEAP_SIZE
83 : // @DisplayName: Scripting Heap Size
84 : // @Description: Amount of memory available for scripting
85 : // @Range: 1024 1048576
86 : // @Increment: 1024
87 : // @User: Advanced
88 : // @RebootRequired: True
89 : AP_GROUPINFO("HEAP_SIZE", 3, AP_Scripting, _script_heap_size, SCRIPTING_HEAP_SIZE),
90 :
91 : // @Param: DEBUG_OPTS
92 : // @DisplayName: Scripting Debug Level
93 : // @Description: Debugging options
94 : // @Bitmask: 0: No Scripts to run message if all scripts have stopped
95 : // @Bitmask: 1: Runtime messages for memory usage and execution time
96 : // @Bitmask: 2: Suppress logging scripts to dataflash
97 : // @Bitmask: 3: log runtime memory usage and execution time
98 : // @Bitmask: 4: Disable pre-arm check
99 : // @Bitmask: 5: Save CRC of current scripts to loaded and running checksum parameters enabling pre-arm
100 : // @Bitmask: 6: Disable heap expansion on allocation failure
101 : // @User: Advanced
102 : AP_GROUPINFO("DEBUG_OPTS", 4, AP_Scripting, _debug_options, 0),
103 :
104 : // @Param: USER1
105 : // @DisplayName: Scripting User Parameter1
106 : // @Description: General purpose user variable input for scripts
107 : // @User: Standard
108 : AP_GROUPINFO("USER1", 5, AP_Scripting, _user[0], 0.0),
109 :
110 : // @Param: USER2
111 : // @DisplayName: Scripting User Parameter2
112 : // @Description: General purpose user variable input for scripts
113 : // @User: Standard
114 : AP_GROUPINFO("USER2", 6, AP_Scripting, _user[1], 0.0),
115 :
116 : // @Param: USER3
117 : // @DisplayName: Scripting User Parameter3
118 : // @Description: General purpose user variable input for scripts
119 : // @User: Standard
120 : AP_GROUPINFO("USER3", 7, AP_Scripting, _user[2], 0.0),
121 :
122 : // @Param: USER4
123 : // @DisplayName: Scripting User Parameter4
124 : // @Description: General purpose user variable input for scripts
125 : // @User: Standard
126 : AP_GROUPINFO("USER4", 8, AP_Scripting, _user[3], 0.0),
127 :
128 : // @Param: USER5
129 : // @DisplayName: Scripting User Parameter5
130 : // @Description: General purpose user variable input for scripts
131 : // @User: Standard
132 : AP_GROUPINFO("USER5", 10, AP_Scripting, _user[4], 0.0),
133 :
134 : // @Param: USER6
135 : // @DisplayName: Scripting User Parameter6
136 : // @Description: General purpose user variable input for scripts
137 : // @User: Standard
138 : AP_GROUPINFO("USER6", 11, AP_Scripting, _user[5], 0.0),
139 :
140 : // @Param: DIR_DISABLE
141 : // @DisplayName: Directory disable
142 : // @Description: This will stop scripts being loaded from the given locations
143 : // @Bitmask: 0:ROMFS, 1:APM/scripts
144 : // @RebootRequired: True
145 : // @User: Advanced
146 : AP_GROUPINFO("DIR_DISABLE", 9, AP_Scripting, _dir_disable, 0),
147 :
148 : // @Param: LD_CHECKSUM
149 : // @DisplayName: Loaded script checksum
150 : // @Description: Required XOR of CRC32 checksum of loaded scripts, vehicle will not arm with incorrect scripts loaded, -1 disables
151 : // @User: Advanced
152 : AP_GROUPINFO("LD_CHECKSUM", 12, AP_Scripting, _required_loaded_checksum, -1),
153 :
154 : // @Param: RUN_CHECKSUM
155 : // @DisplayName: Running script checksum
156 : // @Description: Required XOR of CRC32 checksum of running scripts, vehicle will not arm with incorrect scripts running, -1 disables
157 : // @User: Advanced
158 : AP_GROUPINFO("RUN_CHECKSUM", 13, AP_Scripting, _required_running_checksum, -1),
159 :
160 : // @Param: THD_PRIORITY
161 : // @DisplayName: Scripting thread priority
162 : // @Description: This sets the priority of the scripting thread. This is normally set to a low priority to prevent scripts from interfering with other parts of the system. Advanced users can change this priority if scripting needs to be prioritised for realtime applications. WARNING: changing this parameter can impact the stability of your flight controller. The scipting thread priority in this parameter is chosen based on a set of system level priorities for other subsystems. It is strongly recommended that you use the lowest priority that is sufficient for your application. Note that all scripts run at the same priority, so if you raise this priority you must carefully audit all lua scripts for behaviour that does not interfere with the operation of the system.
163 : // @Values: 0:Normal, 1:IO Priority, 2:Storage Priority, 3:UART Priority, 4:I2C Priority, 5:SPI Priority, 6:Timer Priority, 7:Main Priority, 8:Boost Priority
164 : // @RebootRequired: True
165 : // @User: Advanced
166 : AP_GROUPINFO("THD_PRIORITY", 14, AP_Scripting, _thd_priority, uint8_t(ThreadPriority::NORMAL)),
167 :
168 : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
169 : // @Param: SDEV_EN
170 : // @DisplayName: Scripting serial device enable
171 : // @Description: Enable scripting serial devices
172 : // @Values: 0:Disabled, 1:Enabled
173 : // @RebootRequired: True
174 : // @User: Advanced
175 : AP_GROUPINFO_FLAGS("SDEV_EN", 15, AP_Scripting, _serialdevice.enable, 0, AP_PARAM_FLAG_ENABLE),
176 :
177 : // @Param: SDEV1_PROTO
178 : // @DisplayName: Serial protocol of scripting serial device
179 : // @Description: Serial protocol of scripting serial device
180 : // @CopyFieldsFrom: SERIAL1_PROTOCOL
181 : // @RebootRequired: True
182 : // @User: Advanced
183 : AP_GROUPINFO("SDEV1_PROTO", 16, AP_Scripting, _serialdevice.ports[0].state.protocol, -1),
184 :
185 : #if AP_SCRIPTING_SERIALDEVICE_NUM_PORTS > 1
186 : // @Param: SDEV2_PROTO
187 : // @DisplayName: Serial protocol of scripting serial device
188 : // @Description: Serial protocol of scripting serial device
189 : // @CopyFieldsFrom: SCR_SDEV1_PROTO
190 : AP_GROUPINFO("SDEV2_PROTO", 17, AP_Scripting, _serialdevice.ports[1].state.protocol, -1),
191 : #endif
192 :
193 : #if AP_SCRIPTING_SERIALDEVICE_NUM_PORTS > 2
194 : // @Param: SDEV3_PROTO
195 : // @DisplayName: Serial protocol of scripting serial device
196 : // @Description: Serial protocol of scripting serial device
197 : // @CopyFieldsFrom: SCR_SDEV1_PROTO
198 : AP_GROUPINFO("SDEV3_PROTO", 18, AP_Scripting, _serialdevice.ports[2].state.protocol, -1),
199 : #endif
200 : #endif // AP_SCRIPTING_SERIALDEVICE_ENABLED
201 :
202 : // WARNING: additional parameters must be listed before SDEV_EN (but have an
203 : // index after SDEV3_PROTO) so they are not disabled by it!
204 :
205 : AP_GROUPEND
206 : };
207 :
208 14686 : AP_Scripting::AP_Scripting() {
209 2098 : AP_Param::setup_object_defaults(this, var_info);
210 :
211 : #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
212 2096 : if (_singleton != nullptr) {
213 0 : AP_HAL::panic("Scripting must be a singleton");
214 : }
215 : #endif // CONFIG_HAL_BOARD == HAL_BOARD_SITL
216 2098 : _singleton = this;
217 2098 : }
218 :
219 2086 : void AP_Scripting::init(void) {
220 2086 : if (!_enable) {
221 1999 : return;
222 : }
223 :
224 : #if AP_FILESYSTEM_FILE_WRITING_ENABLED
225 87 : if ((_dir_disable & uint16_t(AP_Scripting::SCR_DIR::SCRIPTS)) == 0) {
226 : // Only try creating scripts directory if loading from it is enabled
227 87 : const char *dir_name = SCRIPTING_DIRECTORY;
228 87 : if (AP::FS().mkdir(dir_name)) {
229 87 : if (errno != EEXIST) {
230 0 : GCS_SEND_TEXT(MAV_SEVERITY_INFO, "Scripting: failed to create (%s)", dir_name);
231 : }
232 : }
233 : }
234 : #endif
235 :
236 87 : AP_HAL::Scheduler::priority_base priority = AP_HAL::Scheduler::PRIORITY_SCRIPTING;
237 : static const struct {
238 : ThreadPriority scr_priority;
239 : AP_HAL::Scheduler::priority_base hal_priority;
240 : } priority_map[] = {
241 : { ThreadPriority::NORMAL, AP_HAL::Scheduler::PRIORITY_SCRIPTING },
242 : { ThreadPriority::IO, AP_HAL::Scheduler::PRIORITY_IO },
243 : { ThreadPriority::STORAGE, AP_HAL::Scheduler::PRIORITY_STORAGE },
244 : { ThreadPriority::UART, AP_HAL::Scheduler::PRIORITY_UART },
245 : { ThreadPriority::I2C, AP_HAL::Scheduler::PRIORITY_I2C },
246 : { ThreadPriority::SPI, AP_HAL::Scheduler::PRIORITY_SPI },
247 : { ThreadPriority::TIMER, AP_HAL::Scheduler::PRIORITY_TIMER },
248 : { ThreadPriority::MAIN, AP_HAL::Scheduler::PRIORITY_MAIN },
249 : { ThreadPriority::BOOST, AP_HAL::Scheduler::PRIORITY_BOOST },
250 : };
251 870 : for (const auto &p : priority_map) {
252 783 : if (p.scr_priority == _thd_priority) {
253 87 : priority = p.hal_priority;
254 : }
255 : }
256 :
257 87 : if (!hal.scheduler->thread_create(FUNCTOR_BIND_MEMBER(&AP_Scripting::thread, void),
258 : "Scripting", SCRIPTING_STACK_SIZE, priority, 0)) {
259 0 : GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "Scripting: %s", "failed to start");
260 0 : _thread_failed = true;
261 : }
262 : }
263 :
264 : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
265 2094 : void AP_Scripting::init_serialdevice_ports(void) {
266 2094 : if (!_enable) {
267 2007 : return;
268 : }
269 :
270 87 : _serialdevice.init();
271 : }
272 : #endif
273 :
274 : #if HAL_GCS_ENABLED
275 10 : MAV_RESULT AP_Scripting::handle_command_int_packet(const mavlink_command_int_t &packet) {
276 10 : switch ((SCRIPTING_CMD)packet.param1) {
277 0 : case SCRIPTING_CMD_REPL_START:
278 : case SCRIPTING_CMD_REPL_STOP:
279 0 : return MAV_RESULT_DENIED;
280 :
281 0 : case SCRIPTING_CMD_STOP:
282 0 : _restart = false;
283 0 : _stop = true;
284 0 : return MAV_RESULT_ACCEPTED;
285 10 : case SCRIPTING_CMD_STOP_AND_RESTART:
286 10 : _restart = true;
287 10 : _stop = true;
288 10 : return MAV_RESULT_ACCEPTED;
289 0 : case SCRIPTING_CMD_ENUM_END: // cope with MAVLink generator appending to our enum
290 0 : break;
291 : }
292 :
293 0 : return MAV_RESULT_UNSUPPORTED;
294 : }
295 : #endif
296 :
297 97 : void AP_Scripting::thread(void) {
298 : while (true) {
299 : // reset flags
300 97 : _stop = false;
301 97 : _restart = false;
302 97 : _init_failed = false;
303 :
304 97 : lua_scripts *lua = NEW_NOTHROW lua_scripts(_script_vm_exec_count, _script_heap_size, _debug_options);
305 97 : if (lua == nullptr || !lua->heap_allocated()) {
306 0 : GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Scripting: %s", "Unable to allocate memory");
307 0 : _init_failed = true;
308 : } else {
309 : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
310 : // clear data in serial buffers that the script wasn't ready to
311 : // receive
312 97 : _serialdevice.clear();
313 : #endif
314 : #if AP_ARMING_ENABLED && AP_ARMING_AUX_AUTH_ENABLED
315 : // Clear any dangling pre-arms from previous script loads
316 97 : AP_Arming::get_singleton()->reset_all_aux_auths();
317 : #endif
318 : // run won't return while scripting is still active
319 97 : lua->run();
320 :
321 : // only reachable if the lua backend has died for any reason
322 56 : GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Scripting: %s", "stopped");
323 : }
324 56 : delete lua;
325 56 : lua = nullptr;
326 :
327 : // clear allocated i2c devices
328 280 : for (uint8_t i=0; i<SCRIPTING_MAX_NUM_I2C_DEVICE; i++) {
329 224 : delete _i2c_dev[i];
330 224 : _i2c_dev[i] = nullptr;
331 : }
332 56 : num_i2c_devices = 0;
333 :
334 : // clear allocated PWM sources
335 280 : for (uint8_t i=0; i<SCRIPTING_MAX_NUM_PWM_SOURCE; i++) {
336 224 : if (_pwm_source[i] != nullptr) {
337 0 : delete _pwm_source[i];
338 0 : _pwm_source[i] = nullptr;
339 : }
340 : }
341 56 : num_pwm_source = 0;
342 :
343 : #if AP_NETWORKING_ENABLED
344 : // clear allocated sockets
345 2856 : for (uint8_t i=0; i<SCRIPTING_MAX_NUM_NET_SOCKET; i++) {
346 2800 : if (_net_sockets[i] != nullptr) {
347 2 : delete _net_sockets[i];
348 2 : _net_sockets[i] = nullptr;
349 : }
350 : }
351 : #endif // AP_NETWORKING_ENABLED
352 :
353 : #if AP_SCRIPTING_SERIALDEVICE_ENABLED
354 : // clear data in serial buffers that hasn't been transmitted
355 56 : _serialdevice.clear();
356 : #endif
357 :
358 : #if AP_CRSF_SCRIPTING_ENABLED
359 56 : AP::crsf_telem()->clear_menus();
360 : #endif // AP_CRSF_SCRIPTING_ENABLED
361 :
362 : // Clear blocked commands
363 : {
364 56 : WITH_SEMAPHORE(mavlink_command_block_list_sem);
365 56 : while (mavlink_command_block_list != nullptr) {
366 0 : command_block_list *next_item = mavlink_command_block_list->next;
367 0 : delete mavlink_command_block_list;
368 0 : mavlink_command_block_list = next_item;
369 : }
370 56 : }
371 :
372 56 : bool cleared = false;
373 : while(true) {
374 : // 1hz check if we should restart
375 251 : hal.scheduler->delay(1000);
376 205 : if (!enabled()) {
377 : // enable must be put to 0 and back to 1 to restart from params
378 195 : cleared = true;
379 195 : continue;
380 : }
381 : // must be enabled to get this far
382 10 : if (cleared || _restart) {
383 10 : GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Scripting: %s", "restarted");
384 10 : break;
385 : }
386 0 : if (option_is_set(DebugOption::NO_SCRIPTS_TO_RUN)) {
387 0 : GCS_SEND_TEXT(MAV_SEVERITY_DEBUG, "Scripting: %s", "stopped");
388 : }
389 : }
390 10 : }
391 : }
392 :
393 0 : void AP_Scripting::handle_mission_command(const AP_Mission::Mission_Command& cmd_in)
394 : {
395 : #if AP_MISSION_ENABLED
396 0 : if (!_enable) {
397 0 : return;
398 : }
399 :
400 0 : if (mission_data == nullptr) {
401 : // load buffer
402 0 : mission_data = NEW_NOTHROW ObjectBuffer<struct AP_Scripting::scripting_mission_cmd>(mission_cmd_queue_size);
403 0 : if (mission_data != nullptr && mission_data->get_size() == 0) {
404 0 : delete mission_data;
405 0 : mission_data = nullptr;
406 : }
407 0 : if (mission_data == nullptr) {
408 0 : GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "Scripting: %s", "unable to receive mission command");
409 0 : return;
410 : }
411 : }
412 :
413 0 : struct scripting_mission_cmd cmd {cmd_in.p1,
414 0 : cmd_in.content.scripting.p1,
415 0 : cmd_in.content.scripting.p2,
416 0 : cmd_in.content.scripting.p3,
417 0 : AP_HAL::millis()};
418 :
419 0 : mission_data->push(cmd);
420 : #endif
421 : }
422 :
423 66607 : bool AP_Scripting::arming_checks(size_t buflen, char *buffer) const
424 : {
425 66607 : if (!enabled() || option_is_set(DebugOption::DISABLE_PRE_ARM)) {
426 62538 : return true;
427 : }
428 :
429 4069 : if (_thread_failed) {
430 0 : hal.util->snprintf(buffer, buflen, "Scripting: %s", "failed to start");
431 0 : return false;
432 : }
433 :
434 4069 : if (_init_failed) {
435 0 : hal.util->snprintf(buffer, buflen, "Scripting: %s", "out of memory");
436 0 : return false;
437 : }
438 :
439 4069 : lua_scripts::get_last_error_semaphore()->take_blocking();
440 4069 : const char *error_buf = lua_scripts::get_last_error_message();
441 4069 : if (error_buf != nullptr) {
442 48 : hal.util->snprintf(buffer, buflen, "Scripting: %s", error_buf);
443 48 : lua_scripts::get_last_error_semaphore()->give();
444 48 : return false;
445 : }
446 4021 : lua_scripts::get_last_error_semaphore()->give();
447 :
448 : // Use -1 for disabled, this means we don't have to avoid 0 in the CRC, the sign bit is masked off anyway
449 4021 : if (_required_loaded_checksum != -1) {
450 0 : const uint32_t expected_loaded = (uint32_t)_required_loaded_checksum.get() & checksum_param_mask;
451 0 : const uint32_t loaded = lua_scripts::get_loaded_checksum() & checksum_param_mask;
452 0 : if (expected_loaded != loaded) {
453 0 : hal.util->snprintf(buffer, buflen, "Scripting: loaded CRC incorrect want: 0x%x", (unsigned int)loaded);
454 0 : return false;
455 : }
456 : }
457 :
458 4021 : if (_required_running_checksum != -1) {
459 0 : const uint32_t expected_running = (uint32_t)_required_running_checksum.get() & checksum_param_mask;
460 0 : const uint32_t running = lua_scripts::get_running_checksum() & checksum_param_mask;
461 0 : if (expected_running != running) {
462 0 : hal.util->snprintf(buffer, buflen, "Scripting: running CRC incorrect want: 0x%x", (unsigned int)running);
463 0 : return false;
464 : }
465 : }
466 :
467 4021 : return true;
468 : }
469 :
470 0 : void AP_Scripting::restart_all()
471 : {
472 0 : _restart = true;
473 0 : _stop = true;
474 0 : }
475 :
476 : #if HAL_GCS_ENABLED
477 2784435 : void AP_Scripting::handle_message(const mavlink_message_t &msg, const mavlink_channel_t chan) {
478 2784435 : if (mavlink_data.rx_buffer == nullptr) {
479 2780636 : return;
480 : }
481 :
482 3841 : struct mavlink_msg data {msg, chan, AP_HAL::millis()};
483 :
484 3841 : WITH_SEMAPHORE(mavlink_data.sem);
485 7640 : for (uint16_t i = 0; i < mavlink_data.accept_msg_ids_size; i++) {
486 3841 : if (mavlink_data.accept_msg_ids[i] == UINT32_MAX) {
487 0 : return;
488 : }
489 3841 : if (mavlink_data.accept_msg_ids[i] == msg.msgid) {
490 42 : mavlink_data.rx_buffer->push(data);
491 42 : return;
492 : }
493 : }
494 3841 : }
495 :
496 531154 : bool AP_Scripting::is_handling_command(uint16_t cmd_id)
497 : {
498 531154 : WITH_SEMAPHORE(mavlink_command_block_list_sem);
499 :
500 : // Look in linked list to see if id is registered
501 531154 : if (mavlink_command_block_list != nullptr) {
502 0 : for (command_block_list *item = mavlink_command_block_list; item; item = item->next) {
503 0 : if (item->id == cmd_id) {
504 0 : return true;
505 : }
506 : }
507 : }
508 :
509 531154 : return false;
510 531154 : }
511 : #endif // HAL_GCS_ENABLED
512 :
513 : // Update called at 1Hz from AP_Vehicle
514 149217 : void AP_Scripting::update() {
515 :
516 149217 : save_checksum();
517 :
518 149217 : }
519 :
520 : // Check if DEBUG_OPTS bit has been set to save current checksum values to params
521 149217 : void AP_Scripting::save_checksum() {
522 :
523 149217 : if (!option_is_set(DebugOption::SAVE_CHECKSUM)) {
524 : // Bit not set, nothing to do
525 149217 : return;
526 : }
527 :
528 : // Save two checksum parameters to there current values
529 0 : _required_loaded_checksum.set_and_save(lua_scripts::get_loaded_checksum() & checksum_param_mask);
530 0 : _required_running_checksum.set_and_save(lua_scripts::get_running_checksum() & checksum_param_mask);
531 :
532 : // Un-set debug option bit
533 0 : option_clear(DebugOption::SAVE_CHECKSUM);
534 :
535 0 : GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "Scripting: %s", "saved checksums");
536 :
537 : }
538 :
539 : AP_Scripting *AP_Scripting::_singleton = nullptr;
540 :
541 : namespace AP {
542 95360 : AP_Scripting *scripting() {
543 95360 : return AP_Scripting::get_singleton();
544 : }
545 : }
546 :
547 : #endif // AP_SCRIPTING_ENABLED
|