-- CC:Tweaked + Advanced Peripherals
-- Monitors FE/t on one or two Energy Detectors (e.g., Mekanism Universal Cable)
-- Usage:
-- power_watch [inPeripheral] [outPeripheral] [intervalSeconds]
-- Examples:
-- power_watch -- auto-find two energyDetector peripherals if possible
-- power_watch inDet -- only IN
-- power_watch left right 0.5 -- IN on left, OUT on right, 0.5s interval
local args = { ... }
local sample_interval = tonumber(args[3]) or 1.0
-- Helper: try to resolve a peripheral by exact name/side, else by type
local function resolveDetector(hint)
if hint and peripheral.isPresent(hint) then
local t = peripheral.getType(hint)
if t == "energyDetector" then return peripheral.wrap(hint) end
end
return nil
end
-- Try resolve from args
local inDet = resolveDetector(args[1])
local outDet = resolveDetector(args[2])
-- If not provided, try to auto-find one or two detectors
if not inDet or (args[2] and not outDet) then
local found = { peripheral.find("energyDetector") }
if #found > 0 and not inDet then inDet = found[1] end
if #found > 1 and not outDet then outDet = found[2] end
end
if not inDet and not outDet then
print("Error: No energyDetector peripherals found.")
print("Place Advanced Peripherals 'Energy Detector' blocks inline with your cable,")
print("then attach the computer next to them or via wired modem. Label them if desired.")
return
end
-- Optional monitor
local mon = peripheral.find("monitor")
if mon then
mon.setTextScale(0.5)
mon.setBackgroundColor(colors.black)
mon.setTextColor(colors.white)
mon.clear()
end
-- ring buffer for moving average
local function newAverager(n)
local buf, sum, idx, count = {}, 0, 1, 0
return {
push = function(v)
if count < n then
count = count + 1
else
sum = sum - buf[idx]
end
buf[idx] = v
sum = sum + v
idx = (idx % n) + 1
end,
avg = function() return (count > 0) and (sum / count) or 0 end
}
end
local avgIn = newAverager(10) -- ~10s avg at 1s interval
local avgOut = newAverager(10)
local cumInFE, cumOutFE = 0, 0 -- cumulative FE transferred (approx)
local lastTime = os.epoch("utc") / 1000.0
local function readFEt(det)
if not det then return 0 end
local ok, v = pcall(det.getTransferRate)
if not ok or type(v) ~= "number" then return 0 end
return v
end
local function draw(text)
term.clear()
term.setCursorPos(1,1)
print(text)
if mon then
mon.clear()
mon.setCursorPos(1,1)
mon.write(("Power Watch @ %s"):format(textutils.formatTime(os.time(), true)))
local lines = {}
for line in text:gmatch("[^\n]+") do table.insert(lines, line) end
for i=1,#lines do
mon.setCursorPos(1, i+1)
mon.write(lines[i])
end
end
end
local function fmtFE(v)
-- human readable FE and FE/t
local units = { {1e12, "T"}, {1e9,"G"}, {1e6,"M"}, {1e3,"k"} }
for _,u in ipairs(units) do
if math.abs(v) >= u[1] then return string.format("%.2f %s", v/u[1], u[2]) end
end
return string.format("%.0f", v)
end
while true do
local now = os.epoch("utc") / 1000.0
local dt = math.max(0.001, now - lastTime)
lastTime = now
local inFEt = readFEt(inDet)
local outFEt = readFEt(outDet)
-- Push for moving average
avgIn.push(inFEt)
avgOut.push(outFEt)
-- Integrate to cumulative FE (FE/t * seconds)
cumInFE = cumInFE + inFEt * dt
cumOutFE = cumOutFE + outFEt * dt
local lines = {}
table.insert(lines, "=== CC:T Power Watch (Energy Detectors) ===")
if inDet then
table.insert(lines, string.format(
"IN : %sFE/t (avg %sFE/t) | Total %sFE",
fmtFE(inFEt), fmtFE(avgIn.avg()), fmtFE(cumInFE)
))
else
table.insert(lines, "IN : (not configured)")
end
if outDet then
table.insert(lines, string.format(
"OUT: %sFE/t (avg %sFE/t) | Total %sFE",
fmtFE(outFEt), fmtFE(avgOut.avg()), fmtFE(cumOutFE)
))
else
table.insert(lines, "OUT: (not configured)")
end
table.insert(lines, string.format("Interval: %.2fs Time: %s",
sample_interval, textutils.formatTime(os.time(), true)))
draw(table.concat(lines, "\n"))
sleep(sample_interval)
end