Posted 07 August 2012 - 07:29 PM
Problem:
Elevated High Speed Rail, wanted computer control of multiple switching points, with message routing, configuration files, and local manual control of switch points. Easy to write scripts to automate travel between points on multiplayer world, and GPS enabled all along the route.
Solution:
RailControl 1.0
To Use:
Computer at rail terminal, computers all along the rail line just within range of each other, and computers at switching points all equipped with modems (side doesn't matter).
Each computer needs the terminal numbers to route messages added as 4 digit numeric (ex: terminal 9, entered as 0009). This includes computers that aren't running the program that may want to send or receive messages. Set program as startup and enter information. Once main program is running (routing editing will come up if there is no routeTable file), hiiting 'u' will allow editing the routing table, 'g' will allow you to enter GPS information to allow this computer to act as GPS HOST, and letter for the sides will manually switch on the redstone for that side (first letters except for bottom which is an 'o'). 'x' will exit the program.
To control a switch point near or far, open rednet, send a message of the format "XXXXsb" where XXXX is the terminal side is the side and b is a boolean T or F. Example: rednet.send(7, "0053ft") will communicate to the first relay to send terminal 53 the front redstone needs turned on. sending "XXXXss" will return a status message including GPS coordinates if it is enabled (read code for what the order of the zeroes or ones, or modify to suit yourself).
Play with it, and if you need help, I will do my best… already working on version 2.0:
Next version will have secure mode for controlling that secret door, terminal control for the end stops, and configuration file, version 3 will probably have automatic routing configuration (need to think about that for a while). I will gladly consider ANY feature additions.
Also: If you like my code (or it is just barely acceptable - I see that the copy and paste lost some of the code formatting, blank lines, etc.) and you have ideas or needs that require LUA programming ComputerCraft in a multiplayer environment, contact me privately, I have a bit of free time just now, and I really enjoyed getting this to work.
Thanks for considering,
-Thad (tover153)
Elevated High Speed Rail, wanted computer control of multiple switching points, with message routing, configuration files, and local manual control of switch points. Easy to write scripts to automate travel between points on multiplayer world, and GPS enabled all along the route.
Solution:
RailControl 1.0
To Use:
Computer at rail terminal, computers all along the rail line just within range of each other, and computers at switching points all equipped with modems (side doesn't matter).
Each computer needs the terminal numbers to route messages added as 4 digit numeric (ex: terminal 9, entered as 0009). This includes computers that aren't running the program that may want to send or receive messages. Set program as startup and enter information. Once main program is running (routing editing will come up if there is no routeTable file), hiiting 'u' will allow editing the routing table, 'g' will allow you to enter GPS information to allow this computer to act as GPS HOST, and letter for the sides will manually switch on the redstone for that side (first letters except for bottom which is an 'o'). 'x' will exit the program.
To control a switch point near or far, open rednet, send a message of the format "XXXXsb" where XXXX is the terminal side is the side and b is a boolean T or F. Example: rednet.send(7, "0053ft") will communicate to the first relay to send terminal 53 the front redstone needs turned on. sending "XXXXss" will return a status message including GPS coordinates if it is enabled (read code for what the order of the zeroes or ones, or modify to suit yourself).
Play with it, and if you need help, I will do my best… already working on version 2.0:
Next version will have secure mode for controlling that secret door, terminal control for the end stops, and configuration file, version 3 will probably have automatic routing configuration (need to think about that for a while). I will gladly consider ANY feature additions.
Also: If you like my code (or it is just barely acceptable - I see that the copy and paste lost some of the code formatting, blank lines, etc.) and you have ideas or needs that require LUA programming ComputerCraft in a multiplayer environment, contact me privately, I have a bit of free time just now, and I really enjoyed getting this to work.
Thanks for considering,
-Thad (tover153)
Spoiler
--RailControl
-- Local and remote redstone control and GPS HOST replacement
-- pseudo routing table for network management in complex environments
--
-- TODO:
-- add debug mode with various print messages (probably toggle from menu)
--Translate computerID to 4 digits
local function myID()
local holdID = tostring(os.computerID())
local currentLength = string.len(holdID)
for n = 1, (4 - currentLength) do
holdID = "0" .. holdID
end
return holdID
end
--print header
local function printHeader()
term.clear()
term.setCursorPos(1,1)
print ("Welcome to RailControl")
print ("This program is not Copyright by Thad L. Overturf")
print ("Terminal ", me)
if gpsAvailable then
print("GPS Enabled - location:", gpsX, ",", gpsY, ",", gpsZ)
end
print ()
print ("(f)ront, (b)ack, (r)ight, (l)eft")
print ("(t)op, and b(o)ttom will toggle sides")
print ()
print ("(g) will setup GPS, (u) will edit routes")
print ("(x) to exit")
end
--Open Modem ("borrowed" from GPS code)
local sOpenedSide = nil
local function open()
local bOpen, sFreeSide = false, nil
for n,sSide in pairs(rs.getSides()) do
if peripheral.getType( sSide ) == "modem" then
sFreeSide = sSide
if rednet.isOpen( sSide ) then
bOpen = true
break
end
end
end
if not bOpen then
if sFreeSide then
print( "No modem active. Opening "..sFreeSide.." modem" )
rednet.open( sFreeSide )
sOpenedSide = sFreeSide
return true
else
print( "No modem attached" )
return false
end
end
return true
end
--Close Modem (likewise "borrowed")
function close()
if sOpenedSide then
rednet.close( sOpenedSide )
end
end
--read routing table
local function readRoute()
if not fs.exists("routeTable") then
print("No routing table")
return false
end
r = fs.open("routeTable","r")
routesIn = r.readLine()
r.close()
routes = textutils.unserialize(routesIn)
-- local routeNumber = (string.len(routesIn)) / 4
-- for myCnt = 0, routeNumber - 1 do
-- routes[myCnt] = tonumber(string.sub(routesIn, (myCnt * 4) + 1, (myCnt * 4)+4))
-- print(routes[myCnt])
-- end
return true
end
--send to routing members except originator
local function sendRoute(inText)
for n, routesOut in pairs(routes) do
if tonumber(routesOut) == id then
print("Skipping")
else
rednet.send(tonumber(routesOut), inText)
end
end
end
--send to All routing members
local function sendRouteAll(inText)
for n, routesOut in pairs(routes) do
rednet.send(tonumber(routesOut), inText)
end
end
--check if gps available and read
local function openGPS()
if not fs.exists("location") then
return false
end
g = fs.open("location","r")
gpsString = g.readLine()
gps = textutils.unserialize(gpsString)
gpsX = gps[1]
gpsY = gps[2]
gpsZ = gps[3]
g.close()
return true
end
--create status message
local function makeStatus()
local statusMessage = ""
for n,sSide in pairs(rs.getSides()) do
--statusMessage = statusMessage .. sSide
if rs.getOutput( sSide ) == true then
statusMessage = statusMessage .. "01"
else
statusMessage = statusMessage .. "00"
end
end
if gpsAvailable then
statusMessage = statusMessage .. gpsX .. "X" .. gpsY .. "Y" .. gpsZ .. "Z"
end
return statusMessage
end
--set all redstones
local function setARS(vValue)
for n,sSide in pairs(rs.getSides()) do
rs.setOutput(sSide, vValue)
end
end
--set redstone on side to value
local function setRS(sSide, value)
rs.setOutput (sSide, value)
end
--toggle redstone on a side
local function toggleRS(sSide)
if rs.getOutput(sSide) == true then
rs.setOutput(sSide, false)
else
rs.setOutput(sSide, true)
end
end
--set up GPS
local function setupGPS()
os.pullEventRaw() -- gets g out of keyboard buffer
gw = fs.open("location","w")
write("X: ")
local sX = read(nil)
write("Y: ")
local sY = read(nil)
write("Z: ")
local sZ = read(nil)
gw.write(textutils.serialize({sX,sY,sZ}))
gw.close()
gpsAvailable = openGPS()
printHeader()
return
end
--edit routes
local function editRoutes(show)
--os.pullEventRaw()
--if not fs.exists("routeTable") then
-- rr = fs.open("routeTable","w")
-- rr.close()
--end
term.clear()
term.setCursorPos(1,1)
print("You are editing the routing table, you need")
print("at least one entry, entered as 4 digits")
print(" if this computer should route to computer 9")
print(" then enter 0009 as entry 1 in routing table")
print("delete works off of the record number, so to")
print(" delete record number two, just enter 2")
print()
if show then
print("(l)ist, (a)dd, (d)elete, (w)rite, e(x)it")
end
eEnd = false
while not eEnd do
local event, param1 = os.pullEvent ("char")
if param1 == "l" then
for n, routeArray in pairs(routes) do
print(n, " ", routeArray)
end
end
if param1 == "w" then
local numberOfRoutes = 0
for n,routesInTable in pairs(routes) do
numberOfRoutes = n
end
if numberOfRoutes > 0 then
gw = fs.open("routeTable","w")
gw.write(textutils.serialize(routes))
gw.close()
if numberOfRoutes == 1 then
print (numberOfRoutes, " route written")
else
print (numberOfRoutes, " routes written")
end
else
print("There must be entries in the routing table")
end
end
if param1 == "a" then
local nextNumber = 0
for n, routeArray in pairs(routes) do
nextNumber = n
end
nextNumber = nextNumber + 1
local routeToAdd = read()
routes[nextNumber] = routeToAdd
end
if param1 == "d" then
local numberToDelete = read()
routes[tonumber(numberToDelete)] = nil
end
if param1 == "x" then
if not fs.exists("routeTable") then
print("There must be entries in the routing table")
else
eEnd = true
end
end
print("(l)ist, (a)dd, (d)elete, (w)rite, e(x)it")
end
return true
end
--START PROGRAM
sleep(0.1)
me = myID()
cid = os.computerID()
routes = {}
while not readRoute() do
editRoutes(true)
end
gpsAvailable = openGPS()
printHeader()
if open() then
print("Waiting...")
else
return
end
--print(makeStatus())
bEnd = false
parallel.waitForAll(
function()
while not bEnd do
event, id, text = os.pullEvent()
if event == "key" then
--print(id)
if id == 38 then toggleRS("left") end
if id == 19 then toggleRS("right") end
if id == 33 then toggleRS("front") end
if id == 48 then toggleRS("back") end
if id == 20 then toggleRS("top") end
if id == 24 then toggleRS("bottom") end
if id == 45 then bEnd = true end
if id == 34 then setupGPS() end
if id == 22 then
editRoutes(false)
printHeader()
end
end
if event == "rednet_message" then
if text == "PING" then
if gpsAvailable then
rednet.send(id, textutils.serialize({gpsX,gpsY,gpsZ}))
end
end
dest = string.sub(text, 1, 4)
cmd = string.sub(text, 5, 6)
if dest == me then
print("Remote Message received from ", id, " - ", cmd)
if cmd == "ss" then
sleep(0.4)
sendRouteAll(makeStatus())
end
if cmd == "ft" then setRS("front", true) end
if cmd == "ff" then setRS("front", false) end
if cmd == "bt" then setRS("back", true) end
if cmd == "bf" then setRS("back", false) end
if cmd == "lt" then setRS("left", true) end
if cmd == "lf" then setRS("left", false) end
if cmd == "rt" then setRS("right", true) end
if cmd == "rf" then setRS("right", false) end
if cmd == "tt" then setRS("top", true) end
if cmd == "tf" then setRS("top", false) end
if cmd == "ot" then setRS("bottom", true) end
if cmd == "of" then setRS("bottom", false) end
if cmd == "at" then setARS(true) end
if cmd == "af" then setARS(false) end
else
sendRoute(text)
sleep (0.4)
end
end
end
os.pullEventRaw() -- gets x out of keyboard buffer
end
)