mirror of https://github.com/ArduPilot/ardupilot
AP_Scripting: script switching system
Co-authored-by:Henry Wurzburg (hwurzburg@yahoo.com)
This commit is contained in:
parent
128a6430de
commit
ea89f04a56
|
@ -317,6 +317,12 @@ bool AP_Scripting::arming_checks(size_t buflen, char *buffer) const
|
|||
return true;
|
||||
}
|
||||
|
||||
void AP_Scripting::scripting_restart()
|
||||
{
|
||||
_stop = true;
|
||||
_restart = true;
|
||||
}
|
||||
|
||||
AP_Scripting *AP_Scripting::_singleton = nullptr;
|
||||
|
||||
namespace AP {
|
||||
|
|
|
@ -50,6 +50,8 @@ public:
|
|||
void handle_mission_command(const class AP_Mission::Mission_Command& cmd);
|
||||
|
||||
bool arming_checks(size_t buflen, char *buffer) const;
|
||||
|
||||
void scripting_restart(void);
|
||||
|
||||
// User parameters for inputs into scripts
|
||||
AP_Float _user[6];
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
--[[
|
||||
a script to select other lua scripts using an auxillary switch
|
||||
--]]
|
||||
|
||||
local THIS_SCRIPT = "script_controller.lua"
|
||||
|
||||
--[[
|
||||
copy file src to dest, return true on success
|
||||
--]]
|
||||
function file_copy(src, dest)
|
||||
local block_size = 256
|
||||
local file1 = io.open(src, "rb")
|
||||
if not file1 then
|
||||
return false
|
||||
end
|
||||
local file2 = io.open(dest, "wb")
|
||||
if not file2 then
|
||||
file1:close()
|
||||
return false
|
||||
end
|
||||
while true do
|
||||
local block = file1:read(block_size)
|
||||
if not block then
|
||||
break
|
||||
end
|
||||
file2:write(block)
|
||||
end
|
||||
local ret = false
|
||||
if file1:seek("end") == file2:seek("end") then
|
||||
ret = true
|
||||
end
|
||||
file1:close()
|
||||
file2:close()
|
||||
return ret
|
||||
end
|
||||
|
||||
--[[
|
||||
compare two files, return true if they are the same
|
||||
--]]
|
||||
function file_compare(filename1, filename2)
|
||||
local block_size = 256
|
||||
local file1 = io.open(filename1, "rb")
|
||||
if not file1 then
|
||||
return false
|
||||
end
|
||||
local file2 = io.open(filename2, "rb")
|
||||
if not file2 then
|
||||
file1:close()
|
||||
return false
|
||||
end
|
||||
local ret = true
|
||||
while true do
|
||||
local block1 = file1:read(block_size)
|
||||
local block2 = file2:read(block_size)
|
||||
if block1 ~= block2 then
|
||||
ret = false
|
||||
break
|
||||
end
|
||||
if not block1 then
|
||||
break
|
||||
end
|
||||
end
|
||||
file1:close()
|
||||
file2:close()
|
||||
return ret
|
||||
end
|
||||
|
||||
--[[
|
||||
get the path to the scripts directory. This will be scripts/ on SITL
|
||||
and APM/scripts on a ChibiOS board
|
||||
--]]
|
||||
function get_scripts_dir()
|
||||
local dlist1 = dirlist("APM/scripts")
|
||||
if dlist1 and #dlist1 > 0 then
|
||||
return "APM/scripts"
|
||||
end
|
||||
-- otherwise assume scripts/
|
||||
return "scripts"
|
||||
end
|
||||
|
||||
function file_exists(fname)
|
||||
local f = io.open(fname,"rb")
|
||||
if not f then
|
||||
return false
|
||||
end
|
||||
f:close()
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
remove any lua scripts in the scripts directory that are not in the given subdir
|
||||
returns true if any files were removed
|
||||
--]]
|
||||
function remove_scripts(subdir)
|
||||
local sdir = get_scripts_dir()
|
||||
local dlist = dirlist(sdir)
|
||||
if not dlist then
|
||||
return false
|
||||
end
|
||||
local ret = false
|
||||
for k,v in ipairs(dlist) do
|
||||
local suffix = v:sub(-4)
|
||||
if suffix == ".lua" and v ~= THIS_SCRIPT then
|
||||
if not file_exists(subdir .. "/" .. v) then
|
||||
ret = true
|
||||
remove(sdir .. "/" .. v)
|
||||
end
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
--[[
|
||||
copy scripts from a subdir to the main scripts directory
|
||||
return true if any changes were made
|
||||
--]]
|
||||
function copy_scripts(subdir)
|
||||
local dlist = dirlist(subdir)
|
||||
if not dlist then
|
||||
return false
|
||||
end
|
||||
local ret = false
|
||||
local sdir = get_scripts_dir()
|
||||
for k, v in ipairs(dlist) do
|
||||
local suffix = v:sub(-4)
|
||||
gcs:send_text(0, string.format("checking %s", v))
|
||||
if suffix == ".lua" and v ~= THIS_SCRIPT then
|
||||
local src = subdir .. "/" .. v
|
||||
local dest = sdir .. "/" .. v
|
||||
if not file_compare(src, dest) then
|
||||
ret = true
|
||||
gcs:send_text(0, string.format("copying %s -> %s", src, dest))
|
||||
file_copy(src, dest)
|
||||
else
|
||||
gcs:send_text(0, string.format("same %s -> %s", src, dest))
|
||||
end
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
--[[
|
||||
activate a scripting subdirectory
|
||||
--]]
|
||||
function activate_subdir(n)
|
||||
gcs:send_text(0, string.format("Activating %s", n))
|
||||
-- step1, remove lua files from scripts/ that are not in the givem subdirectory
|
||||
local subdir = get_scripts_dir() .. "/" .. n
|
||||
local changes_made = remove_scripts(subdir)
|
||||
changes_made = changes_made or copy_scripts(subdir)
|
||||
end
|
||||
|
||||
activate_subdir(1)
|
|
@ -2361,3 +2361,19 @@ function follow:get_last_update_ms() end
|
|||
-- desc
|
||||
---@return boolean
|
||||
function follow:have_target() end
|
||||
|
||||
-- desc
|
||||
---@class scripting
|
||||
scripting = {}
|
||||
|
||||
-- desc
|
||||
function scripting:scripting_restart() end
|
||||
|
||||
-- desc
|
||||
--@param directoryname
|
||||
--@return list of filenames
|
||||
function dirlist(directoryname) end
|
||||
|
||||
--desc
|
||||
--@param filename
|
||||
function remove(filename) end
|
||||
|
|
|
@ -356,6 +356,9 @@ userdata Parameter method set_and_save boolean float'skip_check
|
|||
userdata Parameter method configured boolean
|
||||
userdata Parameter method set_default boolean float'skip_check
|
||||
|
||||
include AP_Scripting/AP_Scripting.h
|
||||
singleton AP_Scripting rename scripting
|
||||
singleton AP_Scripting method scripting_restart void
|
||||
|
||||
include AP_Mission/AP_Mission.h
|
||||
singleton AP_Mission rename mission
|
||||
|
@ -635,3 +638,5 @@ userdata uint32_t manual_operator __tostring uint32_t___tostring
|
|||
userdata uint32_t manual toint uint32_t_toint 0
|
||||
userdata uint32_t manual tofloat uint32_t_tofloat 0
|
||||
|
||||
global manual dirlist lua_dirlist 1
|
||||
global manual remove lua_removefile 1
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <AP_Common/AP_Common.h>
|
||||
#include <AP_HAL/HAL.h>
|
||||
#include <AP_Logger/AP_Logger.h>
|
||||
#include <AP_Filesystem/AP_Filesystem.h>
|
||||
|
||||
#include "lua_bindings.h"
|
||||
|
||||
|
@ -494,3 +495,40 @@ int lua_get_CAN_device2(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
#endif // HAL_MAX_CAN_PROTOCOL_DRIVERS
|
||||
|
||||
/*
|
||||
directory listing, return table of files in a directory
|
||||
*/
|
||||
int lua_dirlist(lua_State *L) {
|
||||
struct dirent *entry;
|
||||
int i;
|
||||
const char *path = luaL_checkstring(L, 1);
|
||||
|
||||
/* open directory */
|
||||
auto dir = AP::FS().opendir(path);
|
||||
if (dir == nullptr) { /* error opening the directory? */
|
||||
lua_pushnil(L); /* return nil and ... */
|
||||
lua_pushstring(L, strerror(errno)); /* error message */
|
||||
return 2; /* number of results */
|
||||
}
|
||||
|
||||
/* create result table */
|
||||
lua_newtable(L);
|
||||
i = 1;
|
||||
while ((entry = AP::FS().readdir(dir)) != nullptr) {
|
||||
lua_pushnumber(L, i++); /* push key */
|
||||
lua_pushstring(L, entry->d_name); /* push value */
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
AP::FS().closedir(dir);
|
||||
return 1; /* table is already on top */
|
||||
}
|
||||
|
||||
/*
|
||||
remove a file
|
||||
*/
|
||||
int lua_removefile(lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
return luaL_fileresult(L, remove(filename) == 0, filename);
|
||||
}
|
||||
|
|
|
@ -10,3 +10,5 @@ int lua_get_i2c_device(lua_State *L);
|
|||
int AP_HAL__I2CDevice_read_registers(lua_State *L);
|
||||
int lua_get_CAN_device(lua_State *L);
|
||||
int lua_get_CAN_device2(lua_State *L);
|
||||
int lua_dirlist(lua_State *L);
|
||||
int lua_removefile(lua_State *L);
|
||||
|
|
Loading…
Reference in New Issue