94 lines
2.7 KiB
Lua
94 lines
2.7 KiB
Lua
--[[
|
|
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
|