-- Web Bridge Dashboard for Turtle System -- Beautiful visual interface for 2x3 monitor setup -- Forwards turtle status updates to the web server local SERVER_URL = "http://10.10.10.6:4200" -- Change to your server address local CHANNEL_RECEIVE = 101 local STATUS_CHANNEL = 102 local COMMAND_CHANNEL = 100 -- Find peripherals local modem = peripheral.find("modem") local monitor = peripheral.find("monitor") if not modem then error("No wireless modem found!") end -- Check if we have a monitor for dashboard local hasMonitor = monitor ~= nil if hasMonitor then monitor.setTextScale(0.5) end modem.open(CHANNEL_RECEIVE) modem.open(STATUS_CHANNEL) -- Track turtles and stats local turtles = {} local stats = { messagesReceived = 0, commandsSent = 0, serverUpdates = 0, errors = 0, startTime = os.epoch("utc") } local activityLog = {} -- Dashboard drawing functions (only if monitor available) local function centerText(y, text, fg, bg) if not hasMonitor then return end local w = monitor.getSize() monitor.setCursorPos(math.floor((w - #text) / 2) + 1, y) monitor.setTextColor(fg or colors.white) monitor.setBackgroundColor(bg or colors.black) monitor.write(text) end local function drawBox(x, y, width, height, color) if not hasMonitor then return end monitor.setBackgroundColor(color) for dy = 0, height - 1 do monitor.setCursorPos(x, y + dy) monitor.write(string.rep(" ", width)) end end local function formatTime(ms) local seconds = math.floor(ms / 1000) local minutes = math.floor(seconds / 60) local hours = math.floor(minutes / 60) if hours > 0 then return string.format("%dh %dm", hours, minutes % 60) elseif minutes > 0 then return string.format("%dm %ds", minutes, seconds % 60) else return string.format("%ds", seconds) end end local function getStatusColor(turtle) if not turtle.lastSeen then return colors.red end local timeSince = os.epoch("utc") - turtle.lastSeen if timeSince < 10000 then return colors.lime elseif timeSince < 30000 then return colors.yellow else return colors.red end end local function drawDashboard() if not hasMonitor then return end local w, h = monitor.getSize() monitor.setBackgroundColor(colors.black) monitor.clear() -- Header drawBox(1, 1, w, 3, colors.blue) centerText(2, "=== TURTLE NETWORK BRIDGE ===", colors.white, colors.blue) monitor.setCursorPos(2, 2) monitor.setTextColor(colors.lime) monitor.setBackgroundColor(colors.blue) monitor.write("\7 ONLINE") monitor.setCursorPos(w - 15, 2) monitor.setTextColor(colors.lightBlue) monitor.write("Server: ACTIVE") -- Stats box local startY = 4 drawBox(2, startY, 30, 8, colors.gray) drawBox(3, startY + 1, 28, 6, colors.black) monitor.setTextColor(colors.yellow) monitor.setBackgroundColor(colors.black) monitor.setCursorPos(4, startY + 1) monitor.write("SYSTEM STATISTICS") monitor.setTextColor(colors.lightGray) monitor.setCursorPos(4, startY + 3) monitor.write("Messages Received:") monitor.setTextColor(colors.white) monitor.setCursorPos(23, startY + 3) monitor.write(tostring(stats.messagesReceived)) monitor.setTextColor(colors.lightGray) monitor.setCursorPos(4, startY + 4) monitor.write("Commands Sent:") monitor.setTextColor(colors.lime) monitor.setCursorPos(23, startY + 4) monitor.write(tostring(stats.commandsSent)) monitor.setTextColor(colors.lightGray) monitor.setCursorPos(4, startY + 5) monitor.write("Server Updates:") monitor.setTextColor(colors.lightBlue) monitor.setCursorPos(23, startY + 5) monitor.write(tostring(stats.serverUpdates)) monitor.setTextColor(colors.lightGray) monitor.setCursorPos(4, startY + 6) monitor.write("Uptime:") monitor.setTextColor(colors.white) monitor.setCursorPos(23, startY + 6) monitor.write(formatTime(os.epoch("utc") - stats.startTime)) -- Turtle list local startX = 34 local boxWidth = w - startX - 1 drawBox(startX, startY, boxWidth, 8, colors.gray) drawBox(startX + 1, startY + 1, boxWidth - 2, 6, colors.black) monitor.setTextColor(colors.yellow) monitor.setCursorPos(startX + 2, startY + 1) monitor.write("ACTIVE TURTLES") local y = startY + 3 local count = 0 for id, turtle in pairs(turtles) do if count >= 4 then break end local statusColor = getStatusColor(turtle) monitor.setCursorPos(startX + 2, y) monitor.setTextColor(statusColor) monitor.write("\7") monitor.setTextColor(colors.white) monitor.write(" Turtle #" .. id) monitor.setCursorPos(startX + 16, y) monitor.setTextColor(colors.lightGray) if turtle.state then monitor.write(turtle.state:upper()) else monitor.write("UNKNOWN") end y = y + 1 count = count + 1 end if count == 0 then monitor.setCursorPos(startX + 2, startY + 4) monitor.setTextColor(colors.gray) monitor.write("No turtles detected") end -- Activity log local logY = 13 drawBox(2, logY, w - 2, h - logY - 1, colors.gray) drawBox(3, logY + 1, w - 4, h - logY - 3, colors.black) monitor.setTextColor(colors.yellow) monitor.setCursorPos(4, logY + 1) monitor.write("ACTIVITY LOG") local maxLines = h - logY - 3 for i = 1, math.min(#activityLog, maxLines) do local entry = activityLog[i] monitor.setCursorPos(4, logY + 2 + i - 1) monitor.setBackgroundColor(colors.black) monitor.setTextColor(colors.gray) local time = os.date("%H:%M:%S", entry.time / 1000) monitor.write("[" .. time .. "] ") monitor.setTextColor(entry.color) monitor.write(entry.text) end -- Footer monitor.setBackgroundColor(colors.gray) monitor.setCursorPos(1, h) monitor.clearLine() centerText(h, "Server: " .. SERVER_URL:sub(8), colors.white, colors.gray) end local function addLog(text, color) table.insert(activityLog, 1, {text = text, color = color or colors.white, time = os.epoch("utc")}) if #activityLog > 35 then table.remove(activityLog) end -- Also print to console if no monitor if not hasMonitor then print(text) end end -- Function to send data to web server local function sendToServer(data) local success, result = pcall(function() local jsonData = textutils.serializeJSON(data) local response = http.post( SERVER_URL .. "/api/turtle/update", jsonData, {["Content-Type"] = "application/json"} ) if response then response.close() return true else return false end end) return success and result end -- Function to poll for commands from server local function pollCommands(turtleID) local success, result = pcall(function() local response = http.get(SERVER_URL .. "/api/turtle/" .. turtleID .. "/commands") if response then local content = response.readAll() response.close() local data = textutils.unserializeJSON(content) if data and data.commands then return data.commands end end return {} end) if success then return result else stats.errors = stats.errors + 1 return {} end end -- Initial setup if hasMonitor then drawDashboard() addLog("System initialized with monitor", colors.lime) else print("Web Bridge Started (No monitor)") print("Listening for turtle updates...") print("Server: " .. SERVER_URL) end addLog("Listening on channels " .. STATUS_CHANNEL .. " and " .. CHANNEL_RECEIVE, colors.lightBlue) -- Start polling timer local POLL_INTERVAL = 1 -- Poll every 1 second os.startTimer(POLL_INTERVAL) -- Main loop local lastRefresh = os.epoch("utc") while true do local event, side, channel, replyChannel, message, distance = os.pullEvent() if event == "timer" then -- Poll for commands for all known turtles for turtleID, turtleData in pairs(turtles) do local commands = pollCommands(turtleID) -- Forward commands back to turtle for _, cmd in ipairs(commands) do stats.commandsSent = stats.commandsSent + 1 addLog("CMD: " .. cmd.command .. " -> Turtle #" .. turtleID, colors.yellow) local commandPacket = { command = cmd.command, param = cmd.param, target = turtleID } modem.transmit(COMMAND_CHANNEL, CHANNEL_RECEIVE, commandPacket) -- Debug: show what we're sending if not hasMonitor then print(" Sent to channel " .. COMMAND_CHANNEL .. ": target=" .. turtleID) end end end -- Restart timer os.startTimer(POLL_INTERVAL) -- Refresh display if we have a monitor if hasMonitor then local now = os.epoch("utc") if now - lastRefresh > 2000 then drawDashboard() lastRefresh = now end end elseif event == "modem_message" then -- Only process messages on our channels if channel == STATUS_CHANNEL or channel == CHANNEL_RECEIVE then stats.messagesReceived = stats.messagesReceived + 1 if type(message) == "table" then if message.type == "status" then local turtleID = message.turtleID -- Update turtle data turtles[turtleID] = message turtles[turtleID].lastSeen = os.epoch("utc") addLog("Turtle #" .. turtleID .. " - " .. (message.state or "status"), colors.lightBlue) -- Forward to web server local success = sendToServer(message) if success then stats.serverUpdates = stats.serverUpdates + 1 addLog(" -> Forwarded to server", colors.lime) else stats.errors = stats.errors + 1 addLog(" -> Server error", colors.red) end end end end end end