parent
b2d555933e
commit
5beb83ba9e
@ -0,0 +1,101 @@
|
||||
bc = {}
|
||||
|
||||
_bc_backend = require("_bc_backend")
|
||||
|
||||
function bc:init(master_id)
|
||||
local o = {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
-- Init backend and cb handler
|
||||
o._listen_callbacks = {}
|
||||
o._verb_handlers = {}
|
||||
o._listeners = {}
|
||||
local function cb_handler(cb_type, param, arg)
|
||||
if cb_type == "listen" then
|
||||
if type(o._listen_callbacks[param]) == "function" then
|
||||
o._listen_callbacks[param]()
|
||||
end
|
||||
elseif cb_type == "verb" then
|
||||
o._verb_handlers[param](arg)
|
||||
elseif cb_type == "noun" then
|
||||
return o._mynouns[param]
|
||||
elseif cb_type == "reg_nl" then
|
||||
-- Create array if there is not one already
|
||||
o._listeners[param] = o._listeners[param] or {}
|
||||
-- Insert parameters
|
||||
table.insert(o._listeners[param], arg)
|
||||
return #o._listeners[param]
|
||||
elseif cb_type == "unreg_nl" then
|
||||
o._listeners[param][arg] = true;
|
||||
else
|
||||
error("Wrong cb type")
|
||||
end
|
||||
end
|
||||
o._backend = _bc_backend:init(cb_handler)
|
||||
-- Fetch list of nouns and verbs from master
|
||||
local list = o._backend:fetch_list(master_id)
|
||||
o._nouns = list.nouns
|
||||
o._verbs = list.verbs
|
||||
-- Initialize own nouns
|
||||
o._mynouns = {}
|
||||
for noun, addr in pairs(o._nouns) do
|
||||
if addr == o._backend.local_addr then
|
||||
o._mynouns[noun] = 0
|
||||
end
|
||||
end
|
||||
list = nil
|
||||
return o
|
||||
end
|
||||
|
||||
function bc:get_noun(n)
|
||||
if self._nouns[n] == self._backend.local_addr then
|
||||
return self._mynouns[n]
|
||||
else
|
||||
return self._backend:request_noun(self._nouns[n], n)
|
||||
end
|
||||
end
|
||||
|
||||
function bc:set_noun(n, val)
|
||||
if self._nouns[n] == self._backend.local_addr then
|
||||
-- Call listeners
|
||||
if type(self._listeners[n]) == "table" then
|
||||
for i, listener in ipairs(self._listeners[n]) do
|
||||
-- Check condition
|
||||
if type(listener) == "table" and
|
||||
( (listener.query == "onchange" and self._mynouns[n] ~= val)
|
||||
or (listener.query == "onrising" and self._mynouns[n] < val)
|
||||
or (listener.query == "onfalling" and self._mynouns[n] > val)
|
||||
or (listener.query == "onabove" and val > listener.qparam)
|
||||
or (listener.query == "onbelow" and val < listener.qparam)
|
||||
or (listener.query == "onvalue" and val == listener.qparam)
|
||||
) then
|
||||
self._backend:call_listener(listener.addr, n, i, val)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Set value
|
||||
self._mynouns[n] = val
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function bc:on_verb(v, handler)
|
||||
self._verb_handlers[v] = handler
|
||||
end
|
||||
|
||||
function bc:call_verb(v, param)
|
||||
self._backend:call_verb(self._verbs[v], v, param)
|
||||
end
|
||||
|
||||
function bc:listen_noun(n, query, qparam, cb)
|
||||
local id = self._backend:register_callback(self._nouns[n], n, query, qparam)
|
||||
self._listen_callbacks[id] = cb
|
||||
return id
|
||||
end
|
||||
|
||||
function bc:listen_cancel(n, id)
|
||||
self._backend:cancel_callback(n, id)
|
||||
end
|
||||
|
||||
return bc
|
||||
@ -1,101 +1,154 @@
|
||||
bc = {}
|
||||
-- For testing
|
||||
modem = require("modem")
|
||||
|
||||
-- For deployment
|
||||
-- modem = require("component").modem
|
||||
|
||||
serializer = require("serialization")
|
||||
|
||||
_bc_backend = require("_bc_backend")
|
||||
Queue = {first = 0, last = -1}
|
||||
|
||||
function bc:init(master_id)
|
||||
function Queue:new()
|
||||
local o = {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
-- Init backend and cb handler
|
||||
o._listen_callbacks = {}
|
||||
o._verb_handlers = {}
|
||||
o._listeners = {}
|
||||
local function cb_handler(cb_type, param, arg)
|
||||
if cb_type == "listen" then
|
||||
if type(o._listen_callbacks[param]) == "function" then
|
||||
o._listen_callbacks[param]()
|
||||
end
|
||||
elseif cb_type == "verb" then
|
||||
o._verb_handlers[param](arg)
|
||||
elseif cb_type == "noun" then
|
||||
return o._mynouns[param]
|
||||
elseif cb_type == "reg_nl" then
|
||||
-- Create array if there is not one already
|
||||
o._listeners[param] = o._listeners[param] or {}
|
||||
-- Insert parameters
|
||||
table.insert(o._listeners[param], arg)
|
||||
return #o._listeners[param]
|
||||
elseif cb_type == "unreg_nl" then
|
||||
o._listeners[param][arg] = true;
|
||||
else
|
||||
error("Wrong cb type")
|
||||
end
|
||||
end
|
||||
o._backend = _bc_backend:init(cb_handler)
|
||||
-- Fetch list of nouns and verbs from master
|
||||
local list = o._backend:fetch_list(master_id)
|
||||
o._nouns = list.nouns
|
||||
o._verbs = list.verbs
|
||||
-- Initialize own nouns
|
||||
o._mynouns = {}
|
||||
for noun, addr in pairs(o._nouns) do
|
||||
if addr == o._backend.local_addr then
|
||||
o._mynouns[noun] = 0
|
||||
end
|
||||
end
|
||||
list = nil
|
||||
return o
|
||||
end
|
||||
|
||||
function bc:get_noun(n)
|
||||
if self._nouns[n] == self._backend.local_addr then
|
||||
return self._mynouns[n]
|
||||
else
|
||||
return self._backend:request_noun(self._nouns[n], n)
|
||||
function Queue:insert(value)
|
||||
local last = self.last + 1
|
||||
self.last = last
|
||||
self[last] = value
|
||||
end
|
||||
|
||||
function Queue:isempty()
|
||||
return self.first > self.last
|
||||
end
|
||||
|
||||
function Queue:remove()
|
||||
local first = self.first
|
||||
if self:isempty() then
|
||||
error("Queue is empty")
|
||||
end
|
||||
local value = self[first]
|
||||
self[first] = nil
|
||||
self.first = first + 1
|
||||
return value
|
||||
end
|
||||
|
||||
function bc:set_noun(n, val)
|
||||
if self._nouns[n] == self._backend.local_addr then
|
||||
-- Call listeners
|
||||
if type(self._listeners[n]) == "table" then
|
||||
for i, listener in ipairs(self._listeners[n]) do
|
||||
-- Check condition
|
||||
if type(listener) == "table" and
|
||||
( (listener.query == "onchange" and self._mynouns[n] ~= val)
|
||||
or (listener.query == "onrising" and self._mynouns[n] < val)
|
||||
or (listener.query == "onfalling" and self._mynouns[n] > val)
|
||||
or (listener.query == "onabove" and val > listener.qparam)
|
||||
or (listener.query == "onbelow" and val < listener.qparam)
|
||||
or (listener.query == "onvalue" and val == listener.qparam)
|
||||
) then
|
||||
self._backend:call_listener(listener.addr, n, i, val)
|
||||
message_type = {
|
||||
request_noun = 1,
|
||||
call_verb = 2,
|
||||
noun_response = 3,
|
||||
hello = 4,
|
||||
goodbye = 5,
|
||||
hello_response = 6,
|
||||
}
|
||||
|
||||
CFG_PORT = 1234
|
||||
|
||||
bc = {}
|
||||
|
||||
function bc:init(my_address, local_nouns, local_verbs)
|
||||
local o = {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
o.queue = Queue:new()
|
||||
o.remote_verbs = {}
|
||||
o.remote_nouns = {}
|
||||
-- Modem listener
|
||||
function modem_listener(localAddress, remoteAddress, port, dist, message)
|
||||
dbg = message
|
||||
message = serializer.unserialize(message)
|
||||
if port == CFG_PORT then
|
||||
if message.ty == message_type.request_noun then
|
||||
msg = {ty=message_type.noun_response,
|
||||
noun=message.noun,
|
||||
value=o.local_nouns[message.noun]
|
||||
}
|
||||
o.modem:send(remoteAddress, port, serializer.serialize(msg))
|
||||
elseif message.ty == message_type.noun_response then
|
||||
-- TODO: Make this a bit better, this is dumb
|
||||
o._nr = message.value
|
||||
elseif message.ty == message_type.call_verb then
|
||||
o.local_verbs[message.verb](o, message.param)
|
||||
elseif message.ty == message_type.hello then
|
||||
for i,verb in ipairs(message.verbs) do
|
||||
o.remote_verbs[verb] = remoteAddress
|
||||
end
|
||||
for i,noun in ipairs(message.nouns) do
|
||||
o.remote_nouns[noun] = remoteAddress
|
||||
end
|
||||
-- Respond with own verbs and nouns
|
||||
local mynouns = {}
|
||||
for noun in pairs(o.local_nouns) do
|
||||
table.insert(mynouns, noun)
|
||||
end
|
||||
local myverbs = {}
|
||||
for verb in pairs(o.local_verbs) do
|
||||
table.insert(myverbs, verb)
|
||||
end
|
||||
o.modem:send(remoteAddress, port, serializer.serialize({ty=message_type.hello_response, verbs=myverbs, nouns=mynouns}))
|
||||
elseif message.ty == message_type.hello_response then
|
||||
for i,verb in ipairs(message.verbs) do
|
||||
o.remote_verbs[verb] = remoteAddress
|
||||
end
|
||||
for i,noun in ipairs(message.nouns) do
|
||||
o.remote_nouns[noun] = remoteAddress
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Set value
|
||||
self._mynouns[n] = val
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function bc:on_verb(v, handler)
|
||||
self._verb_handlers[v] = handler
|
||||
-- Change this for deployment VVV
|
||||
o.modem = modem:init(my_address, modem_listener)
|
||||
-- Init local stuff
|
||||
o.local_verbs = local_verbs
|
||||
o.local_nouns = local_nouns
|
||||
-- Send own nouns and verbs and request all remotes to send theirs
|
||||
local mynouns = {}
|
||||
for noun in pairs(local_nouns) do
|
||||
table.insert(mynouns, noun)
|
||||
end
|
||||
local myverbs = {}
|
||||
for verb in pairs(local_verbs) do
|
||||
table.insert(myverbs, verb)
|
||||
end
|
||||
o.modem:broadcast(CFG_PORT, serializer.serialize({ty=message_type.hello, verbs=myverbs, nouns=mynouns}))
|
||||
return o
|
||||
end
|
||||
|
||||
function bc:call_verb(v, param)
|
||||
self._backend:call_verb(self._verbs[v], v, param)
|
||||
function bc:get_noun(n)
|
||||
if self.local_nouns[n] ~= nil then -- This noun is local, makes it easy
|
||||
return self.local_nouns[n]
|
||||
elseif self.remote_nouns[n] ~= nil then -- This noun is remote
|
||||
self.modem:send(self.remote_nouns[n], CFG_PORT, serializer.serialize({ty=message_type.request_noun, noun=n}))
|
||||
while self._nr == nil do
|
||||
-- Nothing, wait for response, TODO: Research performance impact
|
||||
end
|
||||
local value = self._nr
|
||||
self._nr = nil -- Reset
|
||||
return value
|
||||
else
|
||||
error("Noun not found, Node might be offline")
|
||||
end
|
||||
end
|
||||
|
||||
function bc:listen_noun(n, query, qparam, cb)
|
||||
local id = self._backend:register_callback(self._nouns[n], n, query, qparam)
|
||||
self._listen_callbacks[id] = cb
|
||||
return id
|
||||
function bc:set_noun(n, value)
|
||||
if self.local_nouns[n] ~= nil then
|
||||
self.local_nouns[n] = value
|
||||
else
|
||||
error("Can't set remote nouns")
|
||||
end
|
||||
end
|
||||
|
||||
function bc:listen_cancel(n, id)
|
||||
self._backend:cancel_callback(n, id)
|
||||
function bc:call_verb(v, param)
|
||||
if self.local_verbs[v] ~= nil then
|
||||
self.local_verbs[v](self, param)
|
||||
elseif self.remote_verbs[v] ~= nil then
|
||||
self.modem:send(self.remote_verbs[v], CFG_PORT, serializer.serialize({ty=message_type.call_verb, verb=v, param=param}))
|
||||
else
|
||||
error("Verb not found, Node might be offline")
|
||||
end
|
||||
end
|
||||
|
||||
return bc
|
||||
|
||||
Loading…
Reference in new issue