From e50b326deb2701b231df3d01cac5f625f9596142 Mon Sep 17 00:00:00 2001 From: cyberbit Date: Sun, 19 Nov 2023 20:08:24 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=93=A6=20implement=20secure=20modem?= =?UTF-8?q?=20and=20associated=20APIs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/telem/init.lua | 2 +- src/telem/lib/Backplane.lua | 80 +++++++-- src/telem/lib/InputAdapter.lua | 21 +++ src/telem/lib/OutputAdapter.lua | 49 +++++- src/telem/lib/input.lua | 6 +- .../lib/input/SecureModemInputAdapter.lua | 162 ++++++++++++++++++ src/telem/lib/output.lua | 5 +- .../lib/output/SecureModemOutputAdapter.lua | 151 ++++++++++++++++ 8 files changed, 458 insertions(+), 18 deletions(-) create mode 100644 src/telem/lib/input/SecureModemInputAdapter.lua create mode 100644 src/telem/lib/output/SecureModemOutputAdapter.lua diff --git a/src/telem/init.lua b/src/telem/init.lua index eeb404c..b1d6970 100644 --- a/src/telem/init.lua +++ b/src/telem/init.lua @@ -1,5 +1,5 @@ local _Telem = { - _VERSION = '0.2.0', + _VERSION = '0.3.0', util = require 'telem.lib.util', input = require 'telem.lib.input', output = require 'telem.lib.output', diff --git a/src/telem/lib/Backplane.lua b/src/telem/lib/Backplane.lua index 683f565..388f881 100644 --- a/src/telem/lib/Backplane.lua +++ b/src/telem/lib/Backplane.lua @@ -17,6 +17,11 @@ function Backplane:constructor () -- workaround to guarantee processing order self.inputKeys = {} self.outputKeys = {} + + -- last recorded state + self.collection = MetricCollection() + + self.asyncCycleHandlers = {} end -- TODO allow auto-named inputs based on type @@ -24,9 +29,18 @@ function Backplane:addInput (name, input) assert(type(name) == 'string', 'name must be a string') assert(o.instanceof(input, InputAdapter), 'Input must be an InputAdapter') + -- propagate debug state + if self.debugState then + input:debug(self.debugState) + end + self.inputs[name] = input table.insert(self.inputKeys, name) + if input.asyncCycleHandler then + self:addAsyncCycleHandler(name, input.asyncCycleHandler) + end + return self end @@ -34,12 +48,38 @@ function Backplane:addOutput (name, output) assert(type(name) == 'string', 'name must be a string') assert(o.instanceof(output, OutputAdapter), 'Output must be an OutputAdapter') + self:dlog('Backplane:addOutput :: adding output: ' .. name) + + -- propagate debug state + if self.debugState then + output:debug(self.debugState) + end + self.outputs[name] = output table.insert(self.outputKeys, name) + if output.asyncCycleHandler then + self:dlog('Backplane:addOutput :: registering async handler for ' .. name) + + self:addAsyncCycleHandler(name, function () + self:dlog('Backplane:asyncCycleHandler (closure) :: executing async handler for ' .. name) + + local results = {pcall(output.asyncCycleHandler, output)} + + if not table.remove(results, 1) then + t.log('Output fault in async handler for "' .. name .. '":') + t.pprint(table.remove(results, 1)) + end + end) + end + return self end +function Backplane:addAsyncCycleHandler (adapter, handler) + table.insert(self.asyncCycleHandlers, handler) +end + -- NYI function Backplane:processMiddleware () -- @@ -50,16 +90,16 @@ function Backplane:cycle() local tempMetrics = {} local metrics = MetricCollection() - self:dlog(os.date()) - self:dlog('** cycle START !') + self:dlog('Backplane:cycle :: ' .. os.date()) + self:dlog('Backplane:cycle :: cycle START !') - self:dlog('reading inputs...') + self:dlog('Backplane:cycle :: reading inputs...') -- read inputs for _, key in ipairs(self.inputKeys) do local input = self.inputs[key] - self:dlog(' - ' .. key) + self:dlog('Backplane:cycle :: - ' .. key) local results = {pcall(input.read, input)} @@ -71,7 +111,7 @@ function Backplane:cycle() -- attach adapter name for _,v in ipairs(inputMetrics.metrics) do - v.adapter = key + v.adapter = key .. (v.adapter and ':' .. v.adapter or '') table.insert(tempMetrics, v) end @@ -80,9 +120,7 @@ function Backplane:cycle() -- TODO process middleware - -- t.pprint(tempMetrics) - - self:dlog('sorting metrics...') + self:dlog('Backplane:cycle :: sorting metrics...') -- sort -- TODO make this a middleware @@ -91,13 +129,17 @@ function Backplane:cycle() metrics:insert(v) end - self:dlog('writing outputs...') + self:dlog('Backplane:cycle :: saving state...') + + self.collection = metrics + + self:dlog('Backplane:cycle :: writing outputs...') -- write outputs for _, key in pairs(self.outputKeys) do local output = self.outputs[key] - self:dlog(' - ' .. key) + self:dlog('Backplane:cycle :: - ' .. key) local results = {pcall(output.write, output, metrics)} @@ -107,20 +149,34 @@ function Backplane:cycle() end end - self:dlog('** cycle END !') + self:dlog('Backplane:cycle :: cycle END !') return self end -- return a function to cycle this Backplane on a set interval function Backplane:cycleEvery(seconds) - return function() + local selfCycle = function() while true do self:cycle() t.sleep(seconds) end end + + -- TODO + -- this will break support for backplane:cycleEvery(3)() if + -- async-enabled adapters are attached. docs should be updated + -- to either remove the direct launching as an option, or + -- add guidance to all async-enabled adapters to use parallel. + if #{self.asyncCycleHandlers} > 0 then + self:dlog('Backplane:cycleEvery :: found async handlers, returning function list') + + return selfCycle, table.unpack(self.asyncCycleHandlers) + end + + self:dlog('Backplane:cycleEvery :: no async handlers found, returning cycle function') + return selfCycle end function Backplane:debug(debug) diff --git a/src/telem/lib/InputAdapter.lua b/src/telem/lib/InputAdapter.lua index ad7c207..5ecaa0d 100644 --- a/src/telem/lib/InputAdapter.lua +++ b/src/telem/lib/InputAdapter.lua @@ -7,7 +7,10 @@ InputAdapter.type = 'InputAdapter' function InputAdapter:constructor() assert(self.type ~= InputAdapter.type, 'InputAdapter cannot be instantiated') + self.debugState = false + self.prefix = '' + self.asyncCycleHandler = nil -- boot components self:setBoot(function () @@ -23,6 +26,14 @@ function InputAdapter:setBoot(proc) return self.boot end +function InputAdapter:setAsyncCycleHandler(proc) + assert(type(proc) == 'function', 'proc must be a function') + + self.asyncCycleHandler = proc + + return self.asyncCycleHandler +end + function InputAdapter:addComponentByPeripheralID (id) local tempComponent = peripheral.wrap(id) @@ -47,4 +58,14 @@ function InputAdapter:read () t.err(self.type .. ' has not implemented read()') end +function InputAdapter:debug(debug) + self.debugState = debug and true or false + + return self +end + +function InputAdapter:dlog(msg) + if self.debugState then t.log(msg) end +end + return InputAdapter \ No newline at end of file diff --git a/src/telem/lib/OutputAdapter.lua b/src/telem/lib/OutputAdapter.lua index 87cb1ba..28a4e0d 100644 --- a/src/telem/lib/OutputAdapter.lua +++ b/src/telem/lib/OutputAdapter.lua @@ -7,19 +7,62 @@ OutputAdapter.type = 'OutputAdapter' function OutputAdapter:constructor() assert(self.type ~= OutputAdapter.type, 'OutputAdapter cannot be instantiated') - self.components = {} + self.debugState = false + + self.asyncCycleHandler = nil + + -- boot components + self:setBoot(function () + self.components = {} + end)() +end + +function OutputAdapter:setBoot(proc) + assert(type(proc) == 'function', 'proc must be a function') + + self.boot = proc + + return self.boot +end + +function OutputAdapter:setAsyncCycleHandler(proc) + assert(type(proc) == 'function', 'proc must be a function') + + self.asyncCycleHandler = proc + + return self.asyncCycleHandler end function OutputAdapter:addComponentByPeripheralID (id) - self.components.insert(peripheral.wrap(id)) + local tempComponent = peripheral.wrap(id) + + assert(tempComponent, 'Could not find peripheral ID ' .. id) + + self.components[id] = tempComponent end function OutputAdapter:addComponentByPeripheralType (type) - self.components.insert(peripheral.find(type)) + local key = type .. '_' .. #{self.components} + + local tempComponent = peripheral.find(type) + + assert(tempComponent, 'Could not find peripheral type ' .. type) + + self.components[key] = tempComponent end function OutputAdapter:write (metrics) t.err(self.type .. ' has not implemented write()') end +function OutputAdapter:debug(debug) + self.debugState = debug and true or false + + return self +end + +function OutputAdapter:dlog(msg) + if self.debugState then t.log(msg) end +end + return OutputAdapter \ No newline at end of file diff --git a/src/telem/lib/input.lua b/src/telem/lib/input.lua index f369ea8..021d875 100644 --- a/src/telem/lib/input.lua +++ b/src/telem/lib/input.lua @@ -8,10 +8,14 @@ return { refinedStorage = require 'telem.lib.input.RefinedStorageInputAdapter', meStorage = require 'telem.lib.input.MEStorageInputAdapter', + -- machinery mekanism = { fissionReactor = require 'telem.lib.input.mekanism.FissionReactorInputAdapter', inductionMatrix = require 'telem.lib.input.mekanism.InductionMatrixInputAdapter', industrialTurbine = require 'telem.lib.input.mekanism.IndustrialTurbineInputAdapter', fusionReactor = require 'telem.lib.input.mekanism.FusionReactorInputAdapter', - } + }, + + -- modem + secureModem = require 'telem.lib.input.SecureModemInputAdapter' } \ No newline at end of file diff --git a/src/telem/lib/input/SecureModemInputAdapter.lua b/src/telem/lib/input/SecureModemInputAdapter.lua new file mode 100644 index 0000000..3ece471 --- /dev/null +++ b/src/telem/lib/input/SecureModemInputAdapter.lua @@ -0,0 +1,162 @@ +local o = require 'telem.lib.ObjectModel' +local t = require 'telem.lib.util' +local vendor +local ecnet2 +local random + +local InputAdapter = require 'telem.lib.InputAdapter' +local Metric = require 'telem.lib.Metric' +local MetricCollection = require 'telem.lib.MetricCollection' + +local SecureModemInputAdapter = o.class(InputAdapter) +SecureModemInputAdapter.type = 'SecureModemInputAdapter' + + +SecureModemInputAdapter.VERSION = 'v1.0.0' + +SecureModemInputAdapter.REQUEST_PREAMBLE = 'telem://' +SecureModemInputAdapter.REQUESTS = { + GET_COLLECTION = SecureModemInputAdapter.REQUEST_PREAMBLE .. SecureModemInputAdapter.VERSION .. '/collection', +} + +function SecureModemInputAdapter:constructor (peripheralName, address) + self:super('constructor') + + self.inputAddress = address + self.protocol = nil + self.connection = nil + + self.receiveTimeout = 1 + + -- boot components + self:setBoot(function () + self.components = {} + + self:addComponentByPeripheralID(peripheralName) + + if not vendor then + self:dlog('SecureModemInput:boot :: Loading vendor modules...') + + vendor = require 'telem.vendor' + + self:dlog('SecureModemInput:boot :: Vendor modules ready.') + end + + if not random then + self:dlog('SecureModemInput:boot :: Loading ccryptolib.random...') + + random = vendor.ccryptolib.random + + self:dlog('SecureModemInput:boot :: ccryptolib.random ready.') + end + + -- lazy load because it is slow + if not ecnet2 then + self:dlog('SecureModemInput:boot :: Loading ECNet2...') + + ecnet2 = vendor.ecnet2 + + -- TODO fallback initializer when http not available + -- Initialize the random generator. + local postHandle = assert(http.post("https://krist.dev/ws/start", "{}")) + local data = textutils.unserializeJSON(postHandle.readAll()) + postHandle.close() + random.init(data.url) + http.websocket(data.url).close() + + self:dlog('SecureModemInput:boot :: ECNet2 ready. Address = ' .. ecnet2.address()) + end + + self:dlog('SecureModemInput:boot :: Opening modem...') + + ecnet2.open(peripheralName) + + self:dlog('SecureModemInput:boot :: Initializing protocol...') + + self.protocol = ecnet2.Protocol { + -- Programs will only see packets sent on the same protocol. + -- Only one active listener can exist at any time for a given protocol name. + name = "telem", + + -- Objects must be serialized before they are sent over. + serialize = textutils.serialize, + deserialize = textutils.unserialize, + } + + self:dlog('SecureModemInput:boot :: Boot complete.') + end)() +end + +function SecureModemInputAdapter:read () + local _, modem = next(self.components) + local peripheralName = getmetatable(modem).name + + local connect = function () + self:dlog('SecureModemInput:read :: connecting to ' .. self.inputAddress) + + -- TODO come up with better catch mekanism here + self.connection = self.protocol:connect(self.inputAddress, peripheralName) + + local ack = select(2, self.connection:receive(3)) + + if ack then + self:dlog('SecureModemInput:read :: remote ack: ' .. ack) + + -- TODO this is dumb way, make good way + if ack ~= 'telem ' .. self.VERSION then + t.log('SecureModemInput:read :: protocol mismatch: telem ' .. self.VERSION .. ' => ' .. ack) + return false + end + + self:dlog('SecureModemInput:read :: connection established') + return true + end + + t.log('SecureModemInput:read :: ECNet2 connection failed. Please verify remote server is running.') + + self.connection = nil + + return false + end + + self:dlog('SecureModemInput:read :: connected? ' .. tostring(self.connection)) + + if not self.connection and not connect() then + return MetricCollection() + end + + self:dlog('SecureModemInput:read :: sending request to ' .. self.inputAddress) + + local sendResult, errorResult = pcall(self.connection.send, self.connection, self.REQUESTS.GET_COLLECTION) + + if not sendResult then + -- t.pprint(errorResult) + -- self:dlog('SecureModemInput:read :: ') + self:dlog('SecureModemInput:read :: Connection stale, retrying next cycle') + self.connection = nil + return MetricCollection() + end + + self:dlog('SecureModemInput:read :: listening for response') + local sender, collection = self.connection:receive(self.receiveTimeout) + + if not sender then + t.log('SecureModemInput:read :: Receive timed out after ' .. self.receiveTimeout .. ' seconds, retrying next cycle') + + self.connection = nil + + return MetricCollection() + end + + self:dlog('SecureModemInput:read :: response received, hydrating collection') + + local hydratedCollection = MetricCollection() + + for _, value in ipairs(collection.metrics) do + hydratedCollection:insert(Metric(value)) + end + + return hydratedCollection +end + +return SecureModemInputAdapter \ No newline at end of file diff --git a/src/telem/lib/output.lua b/src/telem/lib/output.lua index 796597e..4f10a6c 100644 --- a/src/telem/lib/output.lua +++ b/src/telem/lib/output.lua @@ -8,5 +8,8 @@ return { -- Basalt basalt = { label = require 'telem.lib.output.basalt.LabelOutputAdapter', - } + }, + + -- Modem + secureModem = require 'telem.lib.output.SecureModemOutputAdapter' } \ No newline at end of file diff --git a/src/telem/lib/output/SecureModemOutputAdapter.lua b/src/telem/lib/output/SecureModemOutputAdapter.lua new file mode 100644 index 0000000..4df3fd9 --- /dev/null +++ b/src/telem/lib/output/SecureModemOutputAdapter.lua @@ -0,0 +1,151 @@ +local o = require 'telem.lib.ObjectModel' +local t = require 'telem.lib.util' +local vendor +local ecnet2 +local random + +local OutputAdapter = require 'telem.lib.OutputAdapter' +local MetricCollection = require 'telem.lib.MetricCollection' + +local SecureModemOutputAdapter = o.class(OutputAdapter) +SecureModemOutputAdapter.type = 'SecureModemOutputAdapter' + +SecureModemOutputAdapter.VERSION = 'v1.0.0' + +SecureModemOutputAdapter.REQUEST_PREAMBLE = 'telem://' +SecureModemOutputAdapter.REQUESTS = { + GET_COLLECTION = SecureModemOutputAdapter.REQUEST_PREAMBLE .. SecureModemOutputAdapter.VERSION .. '/collection', +} + +function SecureModemOutputAdapter:constructor (peripheralName) + self:super('constructor') + + self.protocol = nil + self.connections = {} + + -- last recorded state + self.collection = MetricCollection() + + -- TODO test modem disconnect recovery + -- boot components + self:setBoot(function () + self.components = {} + + self:addComponentByPeripheralID(peripheralName) + + if not vendor then + self:dlog('SecureModemInput:boot :: Loading vendor modules...') + + vendor = require 'telem.vendor' + + self:dlog('SecureModemInput:boot :: Vendor modules ready.') + end + + if not random then + self:dlog('SecureModemOutput:boot :: Loading ccryptolib.random...') + + random = vendor.ccryptolib.random + + self:dlog('SecureModemOutput:boot :: ccryptolib.random ready.') + end + + -- lazy load because it is slow + if not ecnet2 then + t.log('SecureModemOutput:boot :: Loading ECNet2...') + + ecnet2 = vendor.ecnet2 + + -- TODO fallback initializer when http not available + -- Initialize the random generator. + local postHandle = assert(http.post("https://krist.dev/ws/start", "{}")) + local data = textutils.unserializeJSON(postHandle.readAll()) + postHandle.close() + random.init(data.url) + http.websocket(data.url).close() + + t.log('SecureModemOutput:boot :: ECNet2 ready. Address = ' .. ecnet2.address()) + end + + self:dlog('SecureModemOutput:boot :: Opening modem...') + + ecnet2.open(peripheralName) + + if not self.protocol then + self:dlog('SecureModemOutput:boot :: Initializing protocol...') + + self.protocol = ecnet2.Protocol { + -- Programs will only see packets sent on the same protocol. + -- Only one active listener can exist at any time for a given protocol name. + name = "telem", + + -- Objects must be serialized before they are sent over. + serialize = textutils.serialize, + deserialize = textutils.unserialize, + } + end + + self:dlog('SecureModemOutput:boot :: Boot complete.') + end)() + + -- register async adapter + self:setAsyncCycleHandler(function () + local listener = self.protocol:listen() + + self:dlog('SecureModemOutput:asyncCycleHandler :: Listener started') + + while true do + local event, id, p2, p3 = os.pullEvent() + + if event == "ecnet2_request" and id == listener.id then + self:dlog('SecureModemOutput:asyncCycleHandler :: received connection from ' .. id) + + self:dlog('SecureModemOutput:asyncCycleHandler :: sending ack...') + + local connection = listener:accept('telem ' .. self.VERSION, p2) + + self.connections[connection.id] = connection + + self:dlog('SecureModemOutput:asyncCycleHandler :: ack sent, connection ' .. connection.id .. ' cached') + elseif event == "ecnet2_message" and self.connections[id] then + self:dlog('SecureModemOutput:asyncCycleHandler :: received request from ' .. p2) + + if p3 == self.REQUESTS.GET_COLLECTION then + self:dlog('SecureModemOutput:asyncCacheHandler :: request = GET_COLLECTION') + + self.connections[id]:send(self.collection) + + self:dlog('SecureModemOutput:asyncCycleHandler :: response sent') + else + t.log('SecureModemOutput: Unknown request: ' .. tostring(p3)) + end + end + + -- if type(message) == 'string' and message:sub(1, #self.REQUEST_PREAMBLE) == self.REQUEST_PREAMBLE then + -- self:dlog('SecureModemOutput:asyncCycleHandler :: received request from ' .. sender) + + -- if message == self.REQUESTS.GET_COLLECTION then + -- self:dlog('SecureModemOutput:asyncCacheHandler :: request = GET_COLLECTION') + + -- self.secureModem.send(sender, self.collection) + + -- self:dlog('SecureModemOutput:asyncCycleHandler :: response sent') + -- else + -- t.log('SecureModemOutput: Unknown request: ' .. tostring(message)) + -- end + -- else + -- self:dlog('SecureModemOutput:asyncCycleHandler :: Ignoring message with missing preamble') + -- end + end + end) +end + +function SecureModemOutputAdapter:write (collection) + self:boot() + + assert(o.instanceof(collection, MetricCollection), 'Collection must be a MetricCollection') + + -- update internal state + self.collection = collection +end + +return SecureModemOutputAdapter \ No newline at end of file From dc83f917fe1563f9c78dd0bbea3133cea814b238 Mon Sep 17 00:00:00 2001 From: cyberbit Date: Sun, 19 Nov 2023 20:14:10 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=91=8C=20remove=20some=20commented=20?= =?UTF-8?q?code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/input/SecureModemInputAdapter.lua | 7 ------- .../lib/output/SecureModemOutputAdapter.lua | 21 ------------------- 2 files changed, 28 deletions(-) diff --git a/src/telem/lib/input/SecureModemInputAdapter.lua b/src/telem/lib/input/SecureModemInputAdapter.lua index 3ece471..630f8be 100644 --- a/src/telem/lib/input/SecureModemInputAdapter.lua +++ b/src/telem/lib/input/SecureModemInputAdapter.lua @@ -57,7 +57,6 @@ function SecureModemInputAdapter:constructor (peripheralName, address) ecnet2 = vendor.ecnet2 -- TODO fallback initializer when http not available - -- Initialize the random generator. local postHandle = assert(http.post("https://krist.dev/ws/start", "{}")) local data = textutils.unserializeJSON(postHandle.readAll()) postHandle.close() @@ -74,11 +73,7 @@ function SecureModemInputAdapter:constructor (peripheralName, address) self:dlog('SecureModemInput:boot :: Initializing protocol...') self.protocol = ecnet2.Protocol { - -- Programs will only see packets sent on the same protocol. - -- Only one active listener can exist at any time for a given protocol name. name = "telem", - - -- Objects must be serialized before they are sent over. serialize = textutils.serialize, deserialize = textutils.unserialize, } @@ -130,8 +125,6 @@ function SecureModemInputAdapter:read () local sendResult, errorResult = pcall(self.connection.send, self.connection, self.REQUESTS.GET_COLLECTION) if not sendResult then - -- t.pprint(errorResult) - -- self:dlog('SecureModemInput:read :: ') self:dlog('SecureModemInput:read :: Connection stale, retrying next cycle') self.connection = nil return MetricCollection() diff --git a/src/telem/lib/output/SecureModemOutputAdapter.lua b/src/telem/lib/output/SecureModemOutputAdapter.lua index 4df3fd9..e27ac00 100644 --- a/src/telem/lib/output/SecureModemOutputAdapter.lua +++ b/src/telem/lib/output/SecureModemOutputAdapter.lua @@ -56,7 +56,6 @@ function SecureModemOutputAdapter:constructor (peripheralName) ecnet2 = vendor.ecnet2 -- TODO fallback initializer when http not available - -- Initialize the random generator. local postHandle = assert(http.post("https://krist.dev/ws/start", "{}")) local data = textutils.unserializeJSON(postHandle.readAll()) postHandle.close() @@ -74,11 +73,7 @@ function SecureModemOutputAdapter:constructor (peripheralName) self:dlog('SecureModemOutput:boot :: Initializing protocol...') self.protocol = ecnet2.Protocol { - -- Programs will only see packets sent on the same protocol. - -- Only one active listener can exist at any time for a given protocol name. name = "telem", - - -- Objects must be serialized before they are sent over. serialize = textutils.serialize, deserialize = textutils.unserialize, } @@ -119,22 +114,6 @@ function SecureModemOutputAdapter:constructor (peripheralName) t.log('SecureModemOutput: Unknown request: ' .. tostring(p3)) end end - - -- if type(message) == 'string' and message:sub(1, #self.REQUEST_PREAMBLE) == self.REQUEST_PREAMBLE then - -- self:dlog('SecureModemOutput:asyncCycleHandler :: received request from ' .. sender) - - -- if message == self.REQUESTS.GET_COLLECTION then - -- self:dlog('SecureModemOutput:asyncCacheHandler :: request = GET_COLLECTION') - - -- self.secureModem.send(sender, self.collection) - - -- self:dlog('SecureModemOutput:asyncCycleHandler :: response sent') - -- else - -- t.log('SecureModemOutput: Unknown request: ' .. tostring(message)) - -- end - -- else - -- self:dlog('SecureModemOutput:asyncCycleHandler :: Ignoring message with missing preamble') - -- end end end) end From 4110c0738bf85bc17b207adb070a6e7a4cdd7019 Mon Sep 17 00:00:00 2001 From: cyberbit Date: Mon, 20 Nov 2023 01:24:46 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=A6=20remove=20collection=20state?= =?UTF-8?q?=20from=20securemodem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit figured out backplane state, will use that instead --- src/telem/lib/Backplane.lua | 2 +- src/telem/lib/output/SecureModemOutputAdapter.lua | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/telem/lib/Backplane.lua b/src/telem/lib/Backplane.lua index 388f881..461a99b 100644 --- a/src/telem/lib/Backplane.lua +++ b/src/telem/lib/Backplane.lua @@ -64,7 +64,7 @@ function Backplane:addOutput (name, output) self:addAsyncCycleHandler(name, function () self:dlog('Backplane:asyncCycleHandler (closure) :: executing async handler for ' .. name) - local results = {pcall(output.asyncCycleHandler, output)} + local results = {pcall(output.asyncCycleHandler, self)} if not table.remove(results, 1) then t.log('Output fault in async handler for "' .. name .. '":') diff --git a/src/telem/lib/output/SecureModemOutputAdapter.lua b/src/telem/lib/output/SecureModemOutputAdapter.lua index e27ac00..b907cf7 100644 --- a/src/telem/lib/output/SecureModemOutputAdapter.lua +++ b/src/telem/lib/output/SecureModemOutputAdapter.lua @@ -23,9 +23,6 @@ function SecureModemOutputAdapter:constructor (peripheralName) self.protocol = nil self.connections = {} - -- last recorded state - self.collection = MetricCollection() - -- TODO test modem disconnect recovery -- boot components self:setBoot(function () @@ -83,7 +80,7 @@ function SecureModemOutputAdapter:constructor (peripheralName) end)() -- register async adapter - self:setAsyncCycleHandler(function () + self:setAsyncCycleHandler(function (backplane) local listener = self.protocol:listen() self:dlog('SecureModemOutput:asyncCycleHandler :: Listener started') @@ -107,7 +104,7 @@ function SecureModemOutputAdapter:constructor (peripheralName) if p3 == self.REQUESTS.GET_COLLECTION then self:dlog('SecureModemOutput:asyncCacheHandler :: request = GET_COLLECTION') - self.connections[id]:send(self.collection) + self.connections[id]:send(backplane.collection) self:dlog('SecureModemOutput:asyncCycleHandler :: response sent') else @@ -123,8 +120,7 @@ function SecureModemOutputAdapter:write (collection) assert(o.instanceof(collection, MetricCollection), 'Collection must be a MetricCollection') - -- update internal state - self.collection = collection + -- no op, all async :) end return SecureModemOutputAdapter \ No newline at end of file