commit 609f4a82aa74f2677aa304d9747688ca7cfec55b Author: Rokas Puzonas Date: Thu May 11 21:53:52 2023 +0300 initial commit diff --git a/.luarc.json b/.luarc.json new file mode 100644 index 0000000..e009664 --- /dev/null +++ b/.luarc.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json", + "Lua.runtime.version": "Lua 5.1", + "Lua.diagnostics.disable": [ + "undefined-field" + ], + "Lua.diagnostics.globals": [ + "peripheral", + "term", + "rednet", + "textutils" + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..bcc5bd8 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Resource monitor + +Setup a multiple computers to monitor inventories and display that information on a portable pocket computer diff --git a/client.lua b/client.lua new file mode 100644 index 0000000..544b4b4 --- /dev/null +++ b/client.lua @@ -0,0 +1,134 @@ +local PROTOCOL = "resource-monitor" +local REFRESH_RATE = 5 -- seconds between every request + +local function pprint(...) + local pretty = require("cc.pretty") + pretty.pretty_print(...) +end + +local function isWirelessModem(peripheral_name) + return peripheral.getType(peripheral_name) == "modem" + and peripheral.call(peripheral_name, "isWireless") +end + +local function getWirelessModem() + for _, name in ipairs(peripheral.getNames()) do + if isWirelessModem(name) then + return name + end + end +end + +local function getItems(servers) + local allItems = {} + for _, id in ipairs(servers) do + rednet.send(id, nil, PROTOCOL) + local _, payload = rednet.receive(PROTOCOL) + local items = textutils.unserialise(payload) + for name, count in pairs(items) do + allItems[name] = (allItems[name] or 0) + count + end + end + + local orderedItems = {} + for name, count in pairs(allItems) do + table.insert(orderedItems, { name = name, count = count }) + end + table.sort(orderedItems, function(a, b) return a.count > b.count end) + return orderedItems +end + +local function getNumberLength(number) + return math.floor(1+math.log10(number)) +end + +local function countColumnWidths(items) + local multiplierWidth = 0 + local remainderWidth = 0 + + for _, item in ipairs(items) do + local multiplier = math.floor(item.count/64) + if multiplier > 0 then + multiplierWidth = math.max(multiplierWidth, getNumberLength(multiplier)) + end + + local remainder = item.count%64 + if remainder > 0 then + remainderWidth = math.max(remainderWidth, getNumberLength(remainder)) + end + end + + return multiplierWidth, remainderWidth +end + +local function writeAlignedNumber(number, width) + local x, y = term.getCursorPos() + term.setCursorPos(x - math.floor(math.log10(number)+1) + width, y) + term.write(number) +end + +local function displayItems(items) + local w, h = term.getSize() + local multiplierColumnWidth, remainderColumnWidth = countColumnWidths(items) + + term.clear() + term.setCursorPos(1, 1) + print("==== Resource monitor ====") + + for i = 1, math.min(#items, h-1) do + local item = items[i] + term.setCursorPos(1, 1+i) + term.write(item.name) + term.write(" ") + + local multiplier = math.floor(item.count/64) + local remainder = item.count%64 + + local y = i+1 + if multiplier > 0 then + local x = w-remainderColumnWidth-2 + if remainderColumnWidth > 0 then + x = x - 1 + end + term.setCursorPos(x, y) + term.write("x64") + + term.setCursorPos(x-multiplierColumnWidth, y) + writeAlignedNumber(multiplier, multiplierColumnWidth) + end + + if remainder > 0 then + term.setCursorPos(w-remainderColumnWidth+1, y) + writeAlignedNumber(remainder, remainderColumnWidth) + end + + if remainder > 0 and multiplier > 0 then + term.setCursorPos(w-remainderColumnWidth, y) + term.write("+") + end + end +end + +local function main() + local modem_name = getWirelessModem() + if not modem_name then + print("ERROR: please attach a wireless modem") + return + end + rednet.open(modem_name) + term.clear() + term.setCursorPos(1, 1) + print("Starting...") + + local servers = {rednet.lookup(PROTOCOL)} + + while true do + local items = getItems(servers) + displayItems(items) + os.sleep(REFRESH_RATE) + end + + rednet.close(modem_name) +end + +main() diff --git a/server.lua b/server.lua new file mode 100644 index 0000000..2e18a2e --- /dev/null +++ b/server.lua @@ -0,0 +1,103 @@ +local PROTOCOL = "resource-monitor" + +local function pprint(...) + local pretty = require("cc.pretty") + pretty.pretty_print(...) +end + +local function isInventory(peripheral_name) + for _, t in ipairs{peripheral.getType(peripheral_name)} do + if t == "inventory" then + return true + end + end + return false +end + +local function isWirelessModem(peripheral_name) + return peripheral.getType(peripheral_name) == "modem" + and peripheral.call(peripheral_name, "isWireless") +end + +local function getInventories() + local inventories = {} + for _, name in ipairs(peripheral.getNames()) do + if isInventory(name) then + table.insert(inventories, name) + end + end + return inventories +end + +local function getWirelessModem() + for _, name in ipairs(peripheral.getNames()) do + if isWirelessModem(name) then + return name + end + end +end + +local function showDiagnostics(hostname, modem_name, inventories) + term.clear() + term.setCursorPos(1, 1) + print("Currently running resource monitor...") + + term.setCursorPos(1, 3) + term.write("Protocol: ") + print(PROTOCOL) + term.write("Hostname: ") + print(hostname) + term.write("Wireless modem: ") + print(modem_name) + + term.setCursorPos(1, 7) + if #inventories == 0 then + term.write("Inventories: None") + else + print("Inventories:") + for _, name in ipairs(inventories) do + term.write("* ") + print(name) + end + end +end + +local function getItems(inventories) + local allItems = {} + for _, inventory in ipairs(inventories) do + for slot, item in pairs(peripheral.call(inventory, "list")) do + local detail = peripheral.call(inventory, "getItemDetail", slot) + local name = detail.displayName + allItems[name] = (allItems[name] or 0) + item.count + end + end + return allItems +end + +local function main(hostname) + if not hostname then + print("ERROR: please provide a hostname") + return + end + + local modem_name = getWirelessModem() + if not modem_name then + print("ERROR: please attach a wireless modem") + return + end + + rednet.open(modem_name) + rednet.host(PROTOCOL, hostname) + + local inventories = getInventories() + + showDiagnostics(hostname, modem_name, inventories) + while true do + local sender = rednet.receive(PROTOCOL) + local items = getItems(inventories) + local payload = textutils.serialise(items, { compact = true }) + rednet.send(sender, payload, PROTOCOL) + end +end + +main(...)