Files and instructions for my "smarthome" setup based on a pile of bash and lua scripts glued together with ddb and runit.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

130 lines
2.8 KiB

local script_name = ...
if not script_name then
print("Usage:")
print(" ddb_logic.lua <script>")
return
end
local output_values = {}
outputs = {
dirty = {},
}
local signal_map = {}
local output_converters = {}
local output_map = {}
inputs = {}
local input_converters = {}
local input_map = {}
setmetatable(outputs, {
__index = function(t,k)
return output_values[k]
end,
__newindex = function (t,k,v)
if output_values[k] ~= v then
output_values[k] = v
t.dirty[k] = true
end
end,
})
local function update_output(output_map, output_converters, outputs)
for k,_ in pairs(outputs.dirty) do
outputs.dirty[k] = nil
local id = output_map[k] or "_ "..k
if outputs[k] == nil then
local cmd = ("u "..id):gsub("\n","")
print(cmd)
else
local converter = output_converters[k] or tostring
local cmd = ("> "..id.." "..converter(outputs[k])):gsub("\n","")
print(cmd)
end
end
end
local function handle_input(input_map, input_converters, key, value, inputs)
local name = input_map[key]
if not name then return false end
local converter = input_converters[name] or tostring
inputs[name] = converter(value)
return true
end
local function handle_signal(signal_map, inputs, outputs, helpers, signal)
local func = signal_map[signal]
if func then
func(inputs, outputs, helpers)
end
end
-- API for subscript
function message(msg)
io.stderr:write(tostring(msg).."\n")
end
function add_signal(global_name, callback)
signal_map[global_name] = callback
end
function add_output(name, global_name, converter, default)
output_values[name] = default
output_converters[name] = converter
output_map[name] = global_name
end
function add_input(name, global_name, converter, default)
inputs[name] = default
input_converters[name] = converter
input_map[global_name] = name
end
dofile(script_name)
add_signal = nil
add_output = nil
add_input = nil
subscribe_to = {}
for k,_ in pairs(signal_map) do
local obj = k:match("(.-) ")
subscribe_to[obj] = true
end
for k,_ in pairs(input_map) do
local obj = k:match("(.-) ")
subscribe_to[obj] = true
print("r "..k)
end
for k,_ in pairs(subscribe_to) do
print("+ "..k)
end
while true do
local i = io.read()
if not i then break end
local key = i:match("^u ([a-zA-z0-9%-_%.]+ [a-zA-z0-9%-_%.]+)$")
if key then
handle_input(input_map, input_converters, key, nil, inputs)
do_logic(inputs, outputs, helpers)
update_output(output_map, output_converters, outputs)
end
local key,value = i:match("> ([a-zA-z0-9%-_%.]+ [a-zA-z0-9%-_%.]+) (.+)$")
if key and value then
handle_input(input_map, input_converters, key, value, inputs)
do_logic(inputs, outputs, helpers)
update_output(output_map, output_converters, outputs)
end
local signal = i:match("^s (.+)$")
if signal then
handle_signal(signal_map, inputs, outputs, helpers, signal)
update_output(output_map, output_converters, outputs)
end
end