diff --git a/sys/apis/peripheral.lua b/sys/apis/peripheral.lua index 4b8178b..b8791b5 100644 --- a/sys/apis/peripheral.lua +++ b/sys/apis/peripheral.lua @@ -1,4 +1,6 @@ -local Util = require('util') +local Event = require('event') +local Socket = require('socket') +local Util = require('util') local Peripheral = Util.shallowCopy(_G.peripheral) @@ -90,6 +92,10 @@ function Peripheral.get(args) args = { type = args } end + if args.device then + return _G.device[args.device] + end + if args.type then local p = Peripheral.getByType(args.type) if p then @@ -112,4 +118,111 @@ function Peripheral.get(args) end end +local function getProxy(pi) + local socket = Socket.connect(pi.host, 189) + + if not socket then + error("Timed out attaching peripheral: " .. pi.uri) + end + + socket:write(pi.path) + local proxy = socket:read(3) + + if not proxy then + error("Timed out attaching peripheral: " .. pi.uri) + end + + local methods = proxy.methods + proxy.methods = nil + + for _,method in pairs(methods) do + proxy[method] = function(...) + socket:write({ fn = method, args = { ... } }) + local resp = socket:read() + if not resp then + error("Timed out communicating with peripheral: " .. pi.uri) + end + return table.unpack(resp) + end + end + + if proxy.blit then + local methods = { 'clear', 'clearLine', 'setCursorPos', 'write', 'blit', + 'setTextColor', 'setTextColour', 'setBackgroundColor', + 'setBackgroundColour', 'scroll', 'setCursorBlink', } + local queue = nil + + for _,method in pairs(methods) do + proxy[method] = function(...) + if not queue then + queue = { } + Event.onTimeout(0, function() + socket:write({ fn = 'fastBlit', args = { queue } }) + queue = nil + socket:read() + end) + end + + table.insert(queue, { + fn = method, + args = { ... }, + }) + end + end + end + + if proxy.type == 'monitor' then + Event.addRoutine(function() + while true do + local event = socket:read() + if not event then + break + end + if not Util.empty(event) then + os.queueEvent(table.unpack(event)) + end + end + end) + end + + return proxy +end + +--[[ + Parse a uri into it's components + + Examples: + monitor = { device = 'monitor' } + side/top = { side = 'top' } + method/list = { method = 'list' } + 12://device/monitor = { host = 12, device = 'monitor' } +]]-- +local function parse(uri) + local pi = Util.split(uri:gsub('^%d*://', ''), '(.-)/') + + if #pi == 1 then + pi = { + 'device', + pi[1], + } + end + + return { + host = uri:match('^(%d*)%:'), -- 12 + uri = uri, -- 12://device/monitor + path = uri:gsub('^%d*://', ''), -- device/monitor + [ pi[1] ] = pi[2], -- device = 'monitor' + } +end + +function Peripheral.lookup(uri) + local pi = parse(uri) + + if pi.host then + return getProxy(pi) + end + + return Peripheral.get(pi) +end + return Peripheral diff --git a/sys/apis/ui.lua b/sys/apis/ui.lua index 3addce4..ca9bed3 100644 --- a/sys/apis/ui.lua +++ b/sys/apis/ui.lua @@ -2,6 +2,7 @@ local Canvas = require('ui.canvas') local class = require('class') local Event = require('event') local Input = require('input') +local Peripheral = require('peripheral') local Transition = require('ui.transition') local Util = require('util') @@ -190,7 +191,7 @@ function Manager:configure(appName, ...) if defaults.device.name == 'terminal' then dev = term.current() else - dev = device[defaults.device.name] + dev = Peripheral.lookup(defaults.device.name) --- device[defaults.device.name] end if not dev then diff --git a/sys/extensions/device.lua b/sys/extensions/device.lua index a67c0a8..2b53733 100644 --- a/sys/extensions/device.lua +++ b/sys/extensions/device.lua @@ -3,3 +3,6 @@ _G.requireInjector() local Peripheral = require('peripheral') _G.device = Peripheral.getList() + +-- register the main term in the devices list +_G.device.terminal = _G.term.current() diff --git a/sys/network/peripheral.lua b/sys/network/peripheral.lua new file mode 100644 index 0000000..ceec9f8 --- /dev/null +++ b/sys/network/peripheral.lua @@ -0,0 +1,68 @@ +--[[ + Allow sharing of local peripherals. +]]-- + +local Event = require('event') +local Peripheral = require('peripheral') +local Socket = require('socket') +local Util = require('util') + +Event.addRoutine(function() + while true do + print('peripheral: listening on port 189') + local socket = Socket.server(189) + + print('peripheral: connection from ' .. socket.dhost) + + Event.addRoutine(function() + local uri = socket:read(2) + if uri then + local peripheral = Peripheral.lookup(uri) + + if peripheral then + print('peripheral: proxing ' .. uri) + local proxy = { + methods = { } + } + + if peripheral.blit then + peripheral = Util.shallowCopy(peripheral) + peripheral.fastBlit = function(data) + for _,v in ipairs(data) do + peripheral[v.fn](unpack(v.args)) + end + end + end + + for k,v in pairs(peripheral) do + if type(v) == 'function' then + table.insert(proxy.methods, k) + else + proxy[k] = v + end + end + + socket:write(proxy) + + if proxy.type == 'monitor' then + local h + h = Event.on('monitor_touch', function(...) + if not socket:write({ ... }) then + Event.off(h) + end + end) + end + + while true do + local data = socket:read() + if not data then + print('peripheral: lost connection from ' .. socket.dhost) + break + end + socket:write({ peripheral[data.fn](table.unpack(data.args)) }) + end + end + end + end) + end +end) diff --git a/sys/network/telnet.lua b/sys/network/telnet.lua index 2ef4143..2b98db8 100644 --- a/sys/network/telnet.lua +++ b/sys/network/telnet.lua @@ -17,7 +17,7 @@ local function telnetHost(socket) local termInfo = socket:read(5) if not termInfo then - _G.printtError('read failed') + _G.printError('read failed') return end