--[[ Storage system uploader for ComputerCraft (CC: Tweaked). Works with both Advanced Peripherals bridges: * "meBridge" -> Applied Energistics 2 (listItems / item.amount) * "rsBridge" -> Refined Storage (getItems / item.count) Periodically reads the network contents and POSTs them to the backend's /api/me-system/update endpoint. NOTE: the backend serves HTTPS with a self-signed certificate by default. CC: Tweaked validates TLS certificates, so either: * point API_URL at an http:// endpoint (run the backend with TLS_ENABLED=false, ideally behind a trusted reverse proxy), or * terminate TLS with a proxy that uses a certificate CC trusts. ]] local API_URL = "https://192.168.2.150:3000/api/me-system/update" local INTERVAL = 10 -- seconds between uploads -- Resolve the bridge peripheral and pick the right method for it. local bridge = peripheral.find("meBridge") local listFn if bridge then listFn = "listItems" else bridge = peripheral.find("rsBridge") if bridge then listFn = "getItems" end end if not bridge then error("No meBridge or rsBridge peripheral found") end if type(bridge[listFn]) ~= "function" then error("Bridge peripheral does not expose " .. listFn .. "()") end local function cleanDisplayName(raw) if type(raw) ~= "string" then return nil end -- ME/RS display names are wrapped in [brackets] — strip them. return (raw:gsub("[%[%]]", "")) end -- Bridges report the same item id once per storage cell. Merge the rows here -- so the backend receives a clean snapshot. local function collect() local items = bridge[listFn](bridge) local byName = {} local order = {} for _, item in ipairs(items) do local amount = item.amount or item.count or 0 local entry = byName[item.name] if entry then entry.amount = entry.amount + amount else entry = { name = item.name, amount = amount, displayName = cleanDisplayName(item.displayName), } byName[item.name] = entry order[#order + 1] = entry end end return order end local function upload(payload) local body = textutils.serializeJSON(payload) local response, err = http.post(API_URL, body, { ["Content-Type"] = "application/json", }) if not response then print("Upload failed: " .. tostring(err)) return end print("Uploaded " .. #payload .. " items -> " .. response.readAll()) response.close() end print("Storage uploader started.") print(" Bridge: " .. listFn) print(" Target: " .. API_URL) while true do local ok, payload = pcall(collect) if ok then pcall(upload, payload) else print("Collect failed: " .. tostring(payload)) end sleep(INTERVAL) end