ardupilot/libraries/AP_Scripting/applets/Script_Controller.lua

260 lines
6.2 KiB
Lua
Raw Normal View History

--[[
a script to select other lua scripts using an auxillary switch from
/1 /2 or /3 subdirectories of the scripts directory
--]]
local THIS_SCRIPT = "Script_Controller.lua"
local sel_ch = Parameter("SCR_USER6")
SEL_CH = sel_ch:get()
if SEL_CH == 0 then
SEL_CH = 302
end
MISSION_FILENAME = "mission.txt"
--[[
check that directory exists
--]]
function check_subdir_exists(n)
return dirlist(get_scripts_dir() .. "/" .. n )
end
--[[
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
--[[
check if a file exists, returns true if it does' fname is complete path to file
--]]
function file_exists(fname)
local f = io.open(fname,"rb")
if not f then
return false
end
f:close()
return true
end
--[[ compare strings case insensitive and return true if match
--]]
function compare_strings_ci(a,b)
return string.upper(a) == string.upper(b)
end
--[[
remove any lua scripts in the scripts directory that are not in the given subdir besides ourselves
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 compare_strings_ci(suffix,".LUA") and not compare_strings_ci(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)
if compare_strings_ci(suffix,".LUA") and not compare_strings_ci(v,THIS_SCRIPT) then
local src = subdir .. "/" .. v
local dest = sdir .. "/" .. v
if not file_compare(src, dest) then
ret = true
file_copy(src, dest)
end
end
end
if ret then
gcs:send_text(5,"Copied new files to scripts directory")
end
return ret
end
--[[
load a mission from a MISSION_FILENAME file in subdirectory n
--]]
function mission_load(n)
file_name = get_scripts_dir() .. "/" .. n .."/" .. MISSION_FILENAME
-- Open file
file = io.open(file_name)
if not file then
return
end
-- check header
assert(string.find(file:read('l'),'QGC WPL 110') == 1, file_name .. ': incorrect format')
-- clear any existing mission
assert(mission:clear(), 'Could not clear current mission')
-- read each line and write to mission
local item = mavlink_mission_item_int_t()
local index = 0
while true do
local data = {}
for i = 1, 12 do
data[i] = file:read('n')
if data[i] == nil then
if i == 1 then
gcs:send_text(6, 'loaded mission: ' .. file_name)
return -- got to the end of the file
else
mission:clear() -- clear part loaded mission
error('failed to read file')
end
end
end
item:seq(data[1])
item:frame(data[3])
item:command(data[4])
item:param1(data[5])
item:param2(data[6])
item:param3(data[7])
item:param4(data[8])
item:x(data[9]*10^7)
item:y(data[10]*10^7)
item:z(data[11])
if not mission:set_item(index,item) then
mission:clear() -- clear part loaded mission
error(string.format('failed to set mission item %i',index))
end
index = index + 1
end
end
--[[
activate a scripting subdirectory
--]]
function activate_subdir(n)
-- step1, remove lua files from scripts/ that are not in the given subdirectory
local subdir = get_scripts_dir() .. "/" .. n
local changes_made = remove_scripts(subdir)
changes_made = changes_made or copy_scripts(subdir) --copy files if different
return changes_made
end
local sw_last = -1
function update()
local sw_current = rc:get_aux_cached(SEL_CH)
if sw_current == sw_last or sw_current == nil then
return update, 500
end
if sw_current == 1 then
subdir = 2
elseif sw_current == 2 then
subdir = 3
else
subdir = 1 --default if RC not established yet
end
sw_last = sw_current
if not check_subdir_exists(subdir) then
gcs:send_text(0,string.format("Scripts subdirectory /%s does not exist!",subdir))
return update, 500
end
changes_made = activate_subdir(subdir)
if changes_made then
scripting:restart_all()
else
mission_load(subdir)
gcs:send_text(0, string.format("Scripts subbdirectory %s active", subdir))
end
return update, 500
end
gcs:send_text(6,"Loaded Script_Controller.lua")
return update, 500