Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --------------------------------------------------------------------------------
- -- Wireless Robot Control Program (Handheld) with Configuration UI
- --
- -- This program runs on your handheld remote computer. It:
- --
- -- 1. Listens for robots to check in (they send "checkin:<name>").
- -- 2. Displays a main list of robots as colored buttons.
- -- 3. When a robot button is touched, shows a submenu with options:
- -- Stats, Start, Stop, Home, Config.
- -- 4. The Stats option sends "stats" and waits for a reply.
- -- 5. The Config option brings up a configuration screen that lets you
- -- adjust the mine width, mine height, and starting facing direction.
- -- (Facing: 0=East, 1=South, 2=West, 3=North.)
- -- 6. The configuration is sent to the robot in the format:
- -- "config:<width>:<height>:<facing>"
- --
- -- Press 'r' to refresh the robot list.
- --------------------------------------------------------------------------------
- -- Open rednet on the modem on the specified side.
- local modemSide = "back"
- if not rednet.isOpen(modemSide) then
- rednet.open(modemSide)
- end
- local robots = {} -- key: robot ID, value: {name, lastCheckin}
- --------------------------------------------------------------------------------
- -- Helper: Draw Button
- --------------------------------------------------------------------------------
- local function drawButton(button)
- term.setBackgroundColor(button.bgColor)
- term.setTextColor(button.textColor)
- for y = button.y1, button.y2 do
- term.setCursorPos(button.x1, y)
- term.write(string.rep(" ", button.x2 - button.x1 + 1))
- end
- local textLength = #button.text
- local btnWidth = button.x2 - button.x1 + 1
- local startX = button.x1 + math.floor((btnWidth - textLength) / 2)
- local centerY = math.floor((button.y1 + button.y2) / 2)
- term.setCursorPos(startX, centerY)
- term.write(button.text)
- end
- local function inButton(x, y, button)
- return x >= button.x1 and x <= button.x2 and y >= button.y1 and y <= button.y2
- end
- --------------------------------------------------------------------------------
- -- Rednet Check-In Listener
- --------------------------------------------------------------------------------
- local function handleRednetMessages()
- while true do
- local sender, message, protocol = rednet.receive()
- if type(message) == "string" then
- local cmd, data = message:match("^(%w+):?(.*)")
- if cmd == "checkin" then
- local name = (data ~= "" and data) or ("Robot " .. sender)
- robots[sender] = { name = name, lastCheckin = os.time() }
- print("Robot checked in: " .. sender .. " (" .. name .. ")")
- end
- end
- end
- end
- --------------------------------------------------------------------------------
- -- Draw Main List of Robots as Buttons
- --------------------------------------------------------------------------------
- local function drawMainList()
- term.clear()
- term.setCursorPos(1,1)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- print("Robot Control Main List (touch a robot)")
- print("Press 'r' to refresh")
- local btns = {}
- local btnY = 4
- local btnHeight = 3
- local btnMargin = 1
- local index = 1
- for id, info in pairs(robots) do
- local btn = {
- x1 = 2,
- y1 = btnY,
- x2 = term.getSize() - 2,
- y2 = btnY + btnHeight - 1,
- bgColor = colors.blue,
- textColor = colors.white,
- text = info.name .. " (ID:" .. id .. ")"
- }
- drawButton(btn)
- btns[index] = { id = id, btn = btn }
- btnY = btnY + btnHeight + btnMargin
- index = index + 1
- end
- return btns
- end
- --------------------------------------------------------------------------------
- -- Draw Submenu for a Selected Robot (Stats, Start, Stop, Home, Config)
- --------------------------------------------------------------------------------
- local function drawRobotMenu(robotId)
- term.clear()
- term.setCursorPos(1,1)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- local robot = robots[robotId]
- print("Robot: " .. robot.name .. " (ID:" .. robotId .. ")")
- print("Select a command:")
- local btnWidth = math.floor((term.getSize() - 6) / 2)
- local btnHeight = 3
- local startX = 2
- local startY = 4
- local cmds = {
- {text="Stats", cmd="stats", bgColor=colors.lime},
- {text="Start", cmd="start", bgColor=colors.green},
- {text="Stop", cmd="stop", bgColor=colors.red},
- {text="Home", cmd="home", bgColor=colors.orange},
- {text="Config", cmd="config", bgColor=colors.cyan}
- }
- local btns = {}
- for i = 1, #cmds do
- local col = ((i - 1) % 2)
- local row = math.floor((i - 1) / 2)
- local btn = {
- x1 = startX + col * (btnWidth + 2),
- y1 = startY + row * (btnHeight + 1),
- x2 = startX + col * (btnWidth + 2) + btnWidth - 1,
- y2 = startY + row * (btnHeight + 1) + btnHeight - 1,
- bgColor = cmds[i].bgColor,
- textColor = colors.white,
- text = cmds[i].text
- }
- drawButton(btn)
- btns[i] = { cmd = cmds[i].cmd, btn = btn }
- end
- local backBtn = {
- x1 = 2,
- y1 = term.getSize() - 3,
- x2 = term.getSize() - 2,
- y2 = term.getSize() - 1,
- bgColor = colors.gray,
- textColor = colors.white,
- text = "Back"
- }
- drawButton(backBtn)
- btns[#cmds+1] = { cmd = "back", btn = backBtn }
- return btns
- end
- --------------------------------------------------------------------------------
- -- Configuration UI for a Robot
- -- Allows setting mine width, height, and starting facing direction.
- --------------------------------------------------------------------------------
- local function configureRobot(robotId)
- local configWidth = 16
- local configHeight = 16
- local configFacing = 0 -- 0=East, 1=South, 2=West, 3=North
- local directions = {"East", "South", "West", "North"}
- local function redrawConfig()
- term.clear()
- term.setCursorPos(1,1)
- print("Configure Robot " .. robotId)
- print("---------------------")
- print("Mine Width: " .. configWidth)
- print("Mine Height: " .. configHeight)
- print("Facing: " .. directions[configFacing+1])
- end
- redrawConfig()
- -- We'll use a simple loop waiting for key presses to adjust values.
- -- For touch, we define colored buttons.
- local btns = {}
- local screenWidth, screenHeight = term.getSize()
- -- Define buttons for width (- and +)
- btns[1] = {cmd="wdec", btn = {x1=2, y1=6, x2=12, y2=8, bgColor=colors.red, textColor=colors.white, text="- Width"}}
- btns[2] = {cmd="winc", btn = {x1=14, y1=6, x2=screenWidth-2, y2=8, bgColor=colors.green, textColor=colors.white, text="+ Width"}}
- -- Buttons for height
- btns[3] = {cmd="hdec", btn = {x1=2, y1=9, x2=12, y2=11, bgColor=colors.red, textColor=colors.white, text="- Height"}}
- btns[4] = {cmd="hinc", btn = {x1=14, y1=9, x2=screenWidth-2, y2=11, bgColor=colors.green, textColor=colors.white, text="+ Height"}}
- -- Buttons for facing
- btns[5] = {cmd="fdec", btn = {x1=2, y1=12, x2=12, y2=14, bgColor=colors.red, textColor=colors.white, text="- Facing"}}
- btns[6] = {cmd="finc", btn = {x1=14, y1=12, x2=screenWidth-2, y2=14, bgColor=colors.green, textColor=colors.white, text="+ Facing"}}
- -- Send and Cancel buttons
- btns[7] = {cmd="send", btn = {x1=2, y1=screenHeight-4, x2=math.floor(screenWidth/2)-1, y2=screenHeight-2, bgColor=colors.lime, textColor=colors.white, text="Send Config"}}
- btns[8] = {cmd="cancel", btn = {x1=math.floor(screenWidth/2)+1, y1=screenHeight-4, x2=screenWidth-2, y2=screenHeight-2, bgColor=colors.gray, textColor=colors.white, text="Cancel"}}
- -- Draw all buttons
- for i = 1, #btns do
- drawButton(btns[i].btn)
- end
- while true do
- local event, button, x, y = os.pullEvent("mouse_click")
- for i = 1, #btns do
- if inButton(x, y, btns[i].btn) then
- local cmd = btns[i].cmd
- if cmd == "wdec" then
- if configWidth > 1 then configWidth = configWidth - 1 end
- elseif cmd == "winc" then
- configWidth = configWidth + 1
- elseif cmd == "hdec" then
- if configHeight > 1 then configHeight = configHeight - 1 end
- elseif cmd == "hinc" then
- configHeight = configHeight + 1
- elseif cmd == "fdec" then
- configFacing = (configFacing - 1) % 4
- elseif cmd == "finc" then
- configFacing = (configFacing + 1) % 4
- elseif cmd == "send" then
- -- Send configuration command to robot
- local configCmd = "config:" .. configWidth .. ":" .. configHeight .. ":" .. configFacing
- rednet.send(robotId, configCmd)
- term.setCursorPos(1,screenHeight-1)
- print("Config sent: " .. configCmd)
- os.sleep(2)
- return
- elseif cmd == "cancel" then
- return
- end
- redrawConfig()
- for j = 1, #btns do drawButton(btns[j].btn) end
- end
- end
- end
- end
- --------------------------------------------------------------------------------
- -- Wait for a button press from a set of buttons; returns the command.
- --------------------------------------------------------------------------------
- local function waitForButtonPress(buttons)
- while true do
- local event, btn, x, y = os.pullEvent("mouse_click")
- for _, data in ipairs(buttons) do
- if inButton(x, y, data.btn) then
- return data.cmd, data.id
- end
- end
- end
- end
- --------------------------------------------------------------------------------
- -- Main UI Loop
- --------------------------------------------------------------------------------
- local function main()
- while true do
- local mainButtons = drawMainList()
- local event, btn, x, y = os.pullEvent("mouse_click")
- for _, data in ipairs(mainButtons) do
- if inButton(x, y, data.btn) then
- local robotId = data.id
- local submenuButtons = drawRobotMenu(robotId)
- while true do
- local cmd, _ = waitForButtonPress(submenuButtons)
- if cmd == "back" then
- break
- elseif cmd == "stats" then
- rednet.send(robotId, "stats")
- term.setCursorPos(2, term.getSize()-5)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- write("Waiting for stats...")
- local sender, reply, protocol = rednet.receive(nil, 3)
- term.clearLine()
- if sender == robotId and reply then
- write("Stats: " .. reply)
- else
- write("No stats received from robot " .. robotId)
- end
- write(" -- Touch to continue.")
- os.pullEvent("mouse_click")
- submenuButtons = drawRobotMenu(robotId)
- elseif cmd == "config" then
- configureRobot(robotId)
- submenuButtons = drawRobotMenu(robotId)
- else
- rednet.send(robotId, cmd)
- term.setCursorPos(2, term.getSize()-5)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- write("Sent command '" .. cmd .. "' to robot " .. robotId)
- os.sleep(1)
- submenuButtons = drawRobotMenu(robotId)
- end
- end
- break
- end
- end
- end
- end
- --------------------------------------------------------------------------------
- -- MAIN: Run the UI and rednet listener in parallel.
- --------------------------------------------------------------------------------
- parallel.waitForAny(main, handleRednetMessages)
- if rednet.isOpen(modemSide) then
- rednet.close(modemSide)
- end
Add Comment
Please, Sign In to add comment