2020-11-15 20:25:38 +01:00
|
|
|
--[[
|
|
|
|
|
|
|
|
SmartLine
|
|
|
|
=========
|
|
|
|
|
|
|
|
Part of the SmartLine mod
|
|
|
|
|
2020-11-20 19:20:28 +01:00
|
|
|
Copyright (C) 2017-2020 Joachim Stolberg
|
2020-11-15 20:25:38 +01:00
|
|
|
|
2020-11-20 19:20:28 +01:00
|
|
|
AGPL v3
|
2020-11-15 20:25:38 +01:00
|
|
|
See LICENSE.txt for more information
|
|
|
|
|
|
|
|
formspec.lua:
|
|
|
|
|
|
|
|
controller formspecs
|
|
|
|
]]--
|
|
|
|
|
|
|
|
smartline.NUM_RULES = 8
|
|
|
|
|
|
|
|
local SIZE = "size[13,8]"
|
|
|
|
|
|
|
|
local sHELP = [[SmartLine Controller Help
|
|
|
|
|
|
|
|
Control other nodes by means of rules like:
|
|
|
|
IF <condition> THEN <action>
|
|
|
|
|
|
|
|
These rules allow to execute actions based on conditions.
|
|
|
|
Examples for conditions are:
|
|
|
|
- the Player Detector detects a player
|
|
|
|
- a button is pressed
|
|
|
|
- a node state is fault, blocked, standby,...
|
|
|
|
|
|
|
|
Actions are:
|
|
|
|
- switch on/off tubelib nodes, like lamps, machines
|
|
|
|
- send chat messages to the owner
|
|
|
|
- output a text message to the display
|
|
|
|
|
|
|
|
The controller executes all rules cyclically.
|
|
|
|
The cycle time for each rule is configurable
|
|
|
|
(1..1000 sec).
|
|
|
|
0 means, the rule will only be called, if
|
|
|
|
the controller received a command from
|
|
|
|
another node, such as buttons.
|
|
|
|
|
|
|
|
Actions can be delayed. Therefore, the
|
|
|
|
'after' value can be set (0..1000 sec).
|
|
|
|
|
|
|
|
Edit command examples:
|
|
|
|
- 'x 1 8' exchange rows 1 with row 8
|
|
|
|
- 'c 1 2' copy row 1 to 2
|
|
|
|
- 'd 3' delete row 3
|
|
|
|
|
|
|
|
The 'outp' tab is for debugging outputs via 'print'
|
|
|
|
The 'notes' tab for your notes.
|
|
|
|
|
|
|
|
The controller needs battery power to work.
|
|
|
|
The battery pack has to be placed near the
|
|
|
|
controller (1 node distance).
|
|
|
|
The needed battery power is directly dependent
|
|
|
|
on the CPU time the controller consumes.
|
|
|
|
|
|
|
|
For more information, see: goo.gl/fF5ap6
|
|
|
|
]]
|
|
|
|
|
|
|
|
-- to simplify the search for a pressed main form button (condition/action)
|
|
|
|
local lButtonKeys = {}
|
|
|
|
|
|
|
|
for idx = 1,smartline.NUM_RULES do
|
|
|
|
lButtonKeys[#lButtonKeys+1] = "cond"..idx
|
|
|
|
lButtonKeys[#lButtonKeys+1] = "actn"..idx
|
|
|
|
end
|
|
|
|
|
|
|
|
local function buttons(s)
|
|
|
|
return "button_exit[7.4,7.5;1.8,1;cancel;Cancel]"..
|
|
|
|
"button[9.3,7.5;1.8,1;save;Save]"..
|
|
|
|
"button[11.2,7.5;1.8,1;"..s.."]"
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.formspecError(meta)
|
|
|
|
local running = meta:get_int("state") == tubelib.RUNNING
|
|
|
|
local cmnd = running and "stop;Stop" or "start;Start"
|
|
|
|
local init = meta:get_string("init")
|
|
|
|
init = minetest.formspec_escape(init)
|
|
|
|
return "size[4,3]"..
|
|
|
|
default.gui_bg..
|
|
|
|
default.gui_bg_img..
|
|
|
|
default.gui_slots..
|
|
|
|
"label[0,0;No Battery?]"..
|
|
|
|
"button[1,2;1.8,1;start;Start]"
|
|
|
|
end
|
|
|
|
|
|
|
|
local function button(data)
|
|
|
|
if data then
|
|
|
|
return data.button
|
|
|
|
else
|
|
|
|
return "..."
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.listing(fs_data)
|
|
|
|
local tbl = {}
|
|
|
|
|
|
|
|
for idx = 1,smartline.NUM_RULES do
|
|
|
|
tbl[#tbl+1] = idx.." ("..fs_data[idx].cycle.."s): IF "..button(fs_data[idx].cond)
|
|
|
|
tbl[#tbl+1] = " THEN "..button(fs_data[idx].actn).." after "..fs_data[idx].after.."s\n"
|
|
|
|
end
|
|
|
|
return table.concat(tbl)
|
|
|
|
end
|
|
|
|
|
|
|
|
local function formspec_rules(fs_data)
|
|
|
|
local tbl = {"field[0,0;0,0;_type_;;main]"..
|
|
|
|
"label[0.4,0;Cycle/s:]label[2.5,0;IF cond:]label[7,0;THEN action:]label[11.5,0;after/s:]"}
|
|
|
|
|
|
|
|
for idx = 1,smartline.NUM_RULES do
|
|
|
|
local ypos = idx * 0.75 - 0.4
|
|
|
|
tbl[#tbl+1] = "label[0,"..(0.2+ypos)..";"..idx.."]"
|
|
|
|
tbl[#tbl+1] = "field[0.7,"..(0.3+ypos)..";1.4,1;cycle"..idx..";;"..(fs_data[idx].cycle or "").."]"
|
|
|
|
tbl[#tbl+1] = "button[1.9,"..ypos..";4.9,1;cond"..idx..";"..minetest.formspec_escape(button(fs_data[idx].cond)).."]"
|
|
|
|
tbl[#tbl+1] = "button[6.8,"..ypos..";4.9,1;actn"..idx..";"..minetest.formspec_escape(button(fs_data[idx].actn)).."]"
|
|
|
|
tbl[#tbl+1] = "field[12,"..(0.3+ypos)..";1.4,1;after"..idx..";;"..(fs_data[idx].after or "").."]"
|
|
|
|
end
|
|
|
|
return table.concat(tbl)
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.store_main_form_data(meta, fields)
|
|
|
|
local fs_data = minetest.deserialize(meta:get_string("fs_data"))
|
|
|
|
for idx = 1,smartline.NUM_RULES do
|
|
|
|
fs_data[idx].cycle = fields["cycle"..idx] or ""
|
|
|
|
fs_data[idx].after = fields["after"..idx] or "0"
|
|
|
|
end
|
|
|
|
meta:set_string("fs_data", minetest.serialize(fs_data))
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.main_form_button_pressed(fields)
|
|
|
|
for _,key in ipairs(lButtonKeys) do
|
|
|
|
if fields[key] then
|
|
|
|
return key
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.formspecSubMenu(meta, key)
|
|
|
|
local fs_data = minetest.deserialize(meta:get_string("fs_data"))
|
|
|
|
if key:sub(1,4) == "cond" then
|
|
|
|
local row = tonumber(key:sub(5,5))
|
|
|
|
return smartline.cond_formspec(row, fs_data[row].cond)
|
|
|
|
else
|
|
|
|
local row = tonumber(key:sub(5,5))
|
|
|
|
return smartline.actn_formspec(row, fs_data[row].actn)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.formspec_button_update(meta, fields)
|
|
|
|
local fs_data = minetest.deserialize(meta:get_string("fs_data"))
|
|
|
|
local row = tonumber(fields._row_ or 1)
|
|
|
|
if fields._col_ == "cond" then
|
|
|
|
fs_data[row].cond = smartline.cond_eval_input(fs_data[row].cond, fields)
|
|
|
|
elseif fields._col_ == "actn" then
|
|
|
|
fs_data[row].actn = smartline.actn_eval_input(fs_data[row].actn, fields)
|
|
|
|
end
|
|
|
|
meta:set_string("fs_data", minetest.serialize(fs_data))
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.cond_formspec_update(meta, fields)
|
|
|
|
local fs_data = minetest.deserialize(meta:get_string("fs_data"))
|
|
|
|
local row = tonumber(fields._row_ or 1)
|
|
|
|
fs_data[row].cond = smartline.cond_eval_input(fs_data[row].cond, fields)
|
|
|
|
meta:set_string("formspec", smartline.cond_formspec(row, fs_data[row].cond))
|
|
|
|
meta:set_string("fs_data", minetest.serialize(fs_data))
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.actn_formspec_update(meta, fields)
|
|
|
|
local fs_data = minetest.deserialize(meta:get_string("fs_data"))
|
|
|
|
local row = tonumber(fields._row_ or 1)
|
|
|
|
fs_data[row].actn = smartline.actn_eval_input(fs_data[row].actn, fields)
|
|
|
|
meta:set_string("formspec", smartline.actn_formspec(row, fs_data[row].actn))
|
|
|
|
meta:set_string("fs_data", minetest.serialize(fs_data))
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function smartline.formspecRules(meta, fs_data, output)
|
|
|
|
local running = meta:get_int("state") == tubelib.RUNNING
|
|
|
|
local cmnd = running and "stop;Stop" or "start;Start"
|
|
|
|
local init = meta:get_string("init")
|
|
|
|
init = minetest.formspec_escape(init)
|
|
|
|
return SIZE..
|
|
|
|
default.gui_bg..
|
|
|
|
default.gui_bg_img..
|
|
|
|
default.gui_slots..
|
|
|
|
"tabheader[0,0;tab;rules,outp,notes,help;1;;true]"..
|
|
|
|
formspec_rules(fs_data)..
|
|
|
|
"label[0.2,7.0;"..output.."]"..
|
|
|
|
"field[0.3,7.8;4,1;cmnd;;<cmnd>]"..
|
|
|
|
"button[4.0,7.5;1.5,1;go;GO]"..
|
|
|
|
buttons(cmnd)
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.formspecOutput(meta)
|
|
|
|
local running = meta:get_int("state") == tubelib.RUNNING
|
|
|
|
local cmnd = running and "stop;Stop" or "start;Start"
|
|
|
|
local output = meta:get_string("output")
|
|
|
|
output = minetest.formspec_escape(output)
|
|
|
|
return SIZE..
|
|
|
|
default.gui_bg..
|
|
|
|
default.gui_bg_img..
|
|
|
|
default.gui_slots..
|
|
|
|
"tabheader[0,0;tab;rules,outp,notes,help;2;;true]"..
|
|
|
|
"textarea[0.3,0.2;13,8.3;output;Output:;"..output.."]"..
|
|
|
|
"button[5.5,7.5;1.8,1;list;List]"..
|
|
|
|
"button[7.4,7.5;1.8,1;clear;Clear]"..
|
|
|
|
"button[9.3,7.5;1.8,1;update;Update]"..
|
|
|
|
"button[11.2,7.5;1.8,1;"..cmnd.."]"
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.formspecNotes(meta)
|
|
|
|
local running = meta:get_int("state") == tubelib.RUNNING
|
|
|
|
local cmnd = running and "stop;Stop" or "start;Start"
|
|
|
|
local notes = meta:get_string("notes") or ""
|
|
|
|
if notes == "" then notes = "<space for your notes>" end
|
|
|
|
notes = minetest.formspec_escape(notes)
|
|
|
|
return SIZE..
|
|
|
|
default.gui_bg..
|
|
|
|
default.gui_bg_img..
|
|
|
|
default.gui_slots..
|
|
|
|
"tabheader[0,0;tab;rules,outp,notes,help;3;;true]"..
|
|
|
|
"textarea[0.3,0.2;13,8.3;notes;Notepad:;"..notes.."]"..
|
|
|
|
buttons(cmnd)
|
|
|
|
end
|
|
|
|
|
|
|
|
function smartline.formspecHelp(offs)
|
|
|
|
return SIZE..
|
|
|
|
default.gui_bg..
|
|
|
|
default.gui_bg_img..
|
|
|
|
default.gui_slots..
|
|
|
|
"tabheader[0,0;tab;rules,outp,notes,help;4;;true]"..
|
|
|
|
"field[0,0;0,0;_type_;;help]"..
|
|
|
|
"label[0,"..(-offs/50)..";"..sHELP.."]"..
|
|
|
|
--"label[0.2,0;test]"..
|
|
|
|
"scrollbar[12,1;0.5,7;vertical;sb_help;"..offs.."]"
|
|
|
|
end
|