276 lines
7.7 KiB
Lua
276 lines
7.7 KiB
Lua
-- Live GPS Tracker for Pocket Computer
|
|
-- Shows your current location in real-time
|
|
|
|
local Channels = require('platform.channels')
|
|
local WebBridge = require('platform.webbridge')
|
|
|
|
local STATUS_CHANNEL = Channels.get('remoteturtle.status')
|
|
|
|
-- Setup modem
|
|
local modem = peripheral.find("modem")
|
|
if not modem then
|
|
error("No wireless modem found!")
|
|
end
|
|
|
|
-- Equip modem if on pocket computer
|
|
if pocket then
|
|
pocket.equipBack()
|
|
modem = peripheral.find("modem")
|
|
end
|
|
|
|
WebBridge.openChannels(modem, { 'remoteturtle.status' })
|
|
|
|
local w, h = term.getSize()
|
|
local myID = os.getComputerID()
|
|
local currentPos = {x = 0, y = 0, z = 0}
|
|
local lastUpdate = 0
|
|
local turtles = {}
|
|
|
|
-- Get GPS position
|
|
local function updateGPS()
|
|
local x, y, z = gps.locate(5)
|
|
if x then
|
|
currentPos = {x = math.floor(x), y = math.floor(y), z = math.floor(z)}
|
|
lastUpdate = os.clock()
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Draw header
|
|
local function drawHeader()
|
|
term.setCursorPos(1, 1)
|
|
term.setBackgroundColor(colors.blue)
|
|
term.setTextColor(colors.white)
|
|
term.clearLine()
|
|
term.setCursorPos(math.floor((w - 14) / 2), 1)
|
|
term.write(" GPS TRACKER ")
|
|
end
|
|
|
|
-- Draw position info
|
|
local function drawPosition()
|
|
term.setBackgroundColor(colors.black)
|
|
term.setTextColor(colors.white)
|
|
|
|
-- Computer ID
|
|
term.setCursorPos(2, 3)
|
|
term.write("Computer ID: ")
|
|
term.setTextColor(colors.yellow)
|
|
term.write(tostring(myID))
|
|
|
|
-- Current coordinates
|
|
term.setTextColor(colors.white)
|
|
term.setCursorPos(2, 5)
|
|
term.write("Current Position:")
|
|
|
|
term.setCursorPos(4, 6)
|
|
term.setTextColor(colors.red)
|
|
term.write("X: ")
|
|
term.setTextColor(colors.white)
|
|
term.write(string.format("%d", currentPos.x))
|
|
|
|
term.setCursorPos(4, 7)
|
|
term.setTextColor(colors.green)
|
|
term.write("Y: ")
|
|
term.setTextColor(colors.white)
|
|
term.write(string.format("%d", currentPos.y))
|
|
|
|
term.setCursorPos(4, 8)
|
|
term.setTextColor(colors.blue)
|
|
term.write("Z: ")
|
|
term.setTextColor(colors.white)
|
|
term.write(string.format("%d", currentPos.z))
|
|
|
|
-- Time since last update
|
|
local timeSince = os.clock() - lastUpdate
|
|
term.setCursorPos(2, 10)
|
|
term.setTextColor(colors.gray)
|
|
if lastUpdate > 0 then
|
|
term.write(string.format("Updated %.1fs ago", timeSince))
|
|
else
|
|
term.write("No GPS fix yet...")
|
|
end
|
|
end
|
|
|
|
-- Draw nearby turtles
|
|
local function drawTurtles()
|
|
term.setBackgroundColor(colors.black)
|
|
term.setTextColor(colors.white)
|
|
|
|
term.setCursorPos(2, 12)
|
|
term.write("Nearby Turtles:")
|
|
|
|
local line = 13
|
|
local count = 0
|
|
|
|
-- Sort turtles by distance
|
|
local sortedTurtles = {}
|
|
for id, data in pairs(turtles) do
|
|
if data.position then
|
|
local dx = data.position.x - currentPos.x
|
|
local dy = data.position.y - currentPos.y
|
|
local dz = data.position.z - currentPos.z
|
|
local distance = math.sqrt(dx*dx + dy*dy + dz*dz)
|
|
table.insert(sortedTurtles, {id = id, data = data, distance = distance})
|
|
end
|
|
end
|
|
|
|
table.sort(sortedTurtles, function(a, b) return a.distance < b.distance end)
|
|
|
|
-- Display up to 5 closest turtles
|
|
for i = 1, math.min(5, #sortedTurtles) do
|
|
local turtle = sortedTurtles[i]
|
|
term.setCursorPos(4, line)
|
|
term.setTextColor(colors.yellow)
|
|
term.write(string.format("#%d", turtle.id))
|
|
term.setTextColor(colors.white)
|
|
term.write(string.format(" [%.1fm]", turtle.distance))
|
|
|
|
term.setCursorPos(6, line + 1)
|
|
term.setTextColor(colors.gray)
|
|
term.write(string.format("(%d, %d, %d)",
|
|
turtle.data.position.x,
|
|
turtle.data.position.y,
|
|
turtle.data.position.z))
|
|
|
|
line = line + 2
|
|
count = count + 1
|
|
if line >= h - 2 then break end
|
|
end
|
|
|
|
if count == 0 then
|
|
term.setCursorPos(4, line)
|
|
term.setTextColor(colors.gray)
|
|
term.write("None detected")
|
|
end
|
|
end
|
|
|
|
-- Draw footer
|
|
local function drawFooter()
|
|
term.setCursorPos(1, h)
|
|
term.setBackgroundColor(colors.gray)
|
|
term.setTextColor(colors.white)
|
|
term.clearLine()
|
|
term.setCursorPos(2, h)
|
|
term.write("[Q] Quit [R] Refresh")
|
|
end
|
|
|
|
-- Full screen refresh
|
|
local function draw()
|
|
term.setBackgroundColor(colors.black)
|
|
term.clear()
|
|
drawHeader()
|
|
drawPosition()
|
|
drawTurtles()
|
|
drawFooter()
|
|
end
|
|
|
|
-- Handle turtle status broadcasts
|
|
local function handleStatus(message)
|
|
if message.id and message.id ~= myID then
|
|
if not turtles[message.id] then
|
|
turtles[message.id] = {}
|
|
end
|
|
|
|
-- Update turtle data
|
|
if message.position then
|
|
turtles[message.id].position = message.position
|
|
end
|
|
if message.status then
|
|
turtles[message.id].status = message.status
|
|
end
|
|
if message.fuel then
|
|
turtles[message.id].fuel = message.fuel
|
|
end
|
|
|
|
turtles[message.id].lastSeen = os.clock()
|
|
end
|
|
end
|
|
|
|
-- Clean up old turtles (not seen in 30 seconds)
|
|
local function cleanupTurtles()
|
|
local now = os.clock()
|
|
for id, data in pairs(turtles) do
|
|
if data.lastSeen and (now - data.lastSeen) > 30 then
|
|
turtles[id] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Main loop
|
|
local function main()
|
|
print("GPS Tracker starting...")
|
|
print("Getting initial GPS fix...")
|
|
|
|
-- Get initial GPS position
|
|
updateGPS()
|
|
|
|
draw()
|
|
|
|
local gpsTimer = os.startTimer(2) -- Update GPS every 2 seconds
|
|
local cleanupTimer = os.startTimer(10) -- Cleanup every 10 seconds
|
|
local drawTimer = os.startTimer(0.5) -- Redraw every 0.5 seconds
|
|
|
|
while true do
|
|
local event, param1, param2, param3, param4, param5 = os.pullEvent()
|
|
|
|
if event == "timer" then
|
|
if param1 == gpsTimer then
|
|
updateGPS()
|
|
gpsTimer = os.startTimer(2)
|
|
elseif param1 == cleanupTimer then
|
|
cleanupTurtles()
|
|
cleanupTimer = os.startTimer(10)
|
|
elseif param1 == drawTimer then
|
|
draw()
|
|
drawTimer = os.startTimer(0.5)
|
|
end
|
|
|
|
elseif event == "modem_message" then
|
|
local channel = param2
|
|
local replyChannel = param3
|
|
local message = param4
|
|
|
|
-- Uses Channels.match() for dual-mode safety: accepts messages on
|
|
-- both legacy (102) and target (4212) channels during migration.
|
|
if Channels.match('remoteturtle.status', channel) and type(message) == "table" then
|
|
handleStatus(message)
|
|
end
|
|
|
|
elseif event == "char" then
|
|
if param1 == "q" or param1 == "Q" then
|
|
term.setBackgroundColor(colors.black)
|
|
term.setTextColor(colors.white)
|
|
term.clear()
|
|
term.setCursorPos(1, 1)
|
|
print("GPS Tracker stopped.")
|
|
return
|
|
elseif param1 == "r" or param1 == "R" then
|
|
updateGPS()
|
|
draw()
|
|
end
|
|
|
|
elseif event == "mouse_click" then
|
|
-- Check if quit button clicked (bottom bar)
|
|
if param3 == h then
|
|
term.setBackgroundColor(colors.black)
|
|
term.setTextColor(colors.white)
|
|
term.clear()
|
|
term.setCursorPos(1, 1)
|
|
print("GPS Tracker stopped.")
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Run the tracker
|
|
local success, err = pcall(main)
|
|
if not success then
|
|
term.setBackgroundColor(colors.black)
|
|
term.setTextColor(colors.white)
|
|
term.clear()
|
|
term.setCursorPos(1, 1)
|
|
print("Error: " .. tostring(err))
|
|
end
|