Rihlsul

ElevatorControl Cabin 1.02

Apr 5th, 2013
767
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.09 KB | None | 0 0
  1. local version = 1.02
  2.  
  3. local CabinConfig = {}
  4. local CabinScreen = {}
  5. local cabinSettingsFile = "Cabin.Settings"
  6.  
  7. local floorDescs = { }
  8. local floorLines = { }
  9. local floorPass = { }
  10.    
  11. local KeepWaiting = true
  12. local Unlocked = true
  13. local relockAlarm = nil
  14.  
  15. -- ######################################################
  16. -- ##  Load the API                                    ##
  17. -- ######################################################
  18.  
  19. if fs.exists("ECAPI") then --Check to make sure that the entered API exists
  20.   os.loadAPI("ECAPI")
  21.   print("ECAPI loaded.")
  22. else
  23.   print("That API does not exist.  Retrieving from PasteBin")
  24.   -- we get it automagically
  25.   shell.run("pastebin","get", "1mcEVzzP", "ECAPI")
  26.   os.loadAPI("ECAPI")
  27.   print("ECAPI loaded.")
  28. end
  29.  
  30.  
  31. -- ######################################################
  32. -- ##  Setup Configuration                             ##
  33. -- ######################################################
  34.  
  35. local DefaultConfig = {}
  36. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Version",version,"Please do not change this.")
  37. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Network","","Elevator network name:")
  38. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Modem","","Which side is the modem?",'side')
  39. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Intro","Please enter a # or X to exit.","User Message:")
  40. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Floor","Floor","Term for floor?")
  41. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"Description","Description","Term for floor descriptions?")
  42. DefaultCongig = ECAPI.addConfigOption(DefaultConfig,"PWTag","SECURE","Tag for secure floors?")
  43. DefaultCongig = ECAPI.addConfigOption(DefaultConfig,"PWShow","","Show secure floors [true/false]?")
  44. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"AccessPW","","Access Password:",'pass')
  45. DefaultConfig = ECAPI.addConfigOption(DefaultConfig,"ConfigPW","","Config. Password:",'pass')   -- note, this is per machine
  46.  
  47. local function networkName()
  48.     return ECAPI.getConfigOption(CabinConfig,"Network")
  49. end
  50.  
  51. local function modemSide()
  52.     return ECAPI.getConfigOption(CabinConfig,"Modem")
  53. end
  54.  
  55. local function floorDesc()
  56.     return ECAPI.getConfigOption(CabinConfig,"Floor")
  57. end
  58.  
  59.  
  60. -- ######################################################
  61. -- ##  Terminal Functions                              ##
  62. -- ######################################################
  63.  
  64. local function termClear()
  65.     ECAPI.printCabinTemplate(CabinConfig)
  66.     CabinScreen = ECAPI.setupScreen(CabinScreen)
  67.     term.setCursorPos(3,18)
  68.     local prompt = ""
  69.     if Unlocked then
  70.         prompt = "Command:"
  71.     else
  72.         prompt = ECAPI.getConfigPrompt(CabinConfig,"AccessPW")
  73.     end
  74.     write(prompt)
  75.     term.setCursorPos(3+string.len(prompt)+1,18)
  76. end
  77.  
  78. local function justPrintLine(newLine)
  79.     if Unlocked then
  80.         CabinScreen = ECAPI.justPrintLine(CabinScreen,newLine)
  81.     end
  82. end
  83.  
  84. local function printFloors(floorDescTable)
  85.     if (floorDescTable ~= nil) then
  86.         local rawTable = textutils.unserialize(floorDescTable)
  87.         for flID, flSettings in pairs(rawTable) do
  88.             floorDescs[flID] = flSettings["Description"]
  89.             if (flSettings['Password'] ~= "") then
  90.                 floorPass[flID] = flSettings['Password']
  91.             end
  92.         end
  93.     end
  94.     termClear()
  95.     term.setCursorPos(1,6)
  96.     if (ECAPI.table_count(floorDescs)) > 0 then
  97.         --print("if check")
  98.         local preX, preY = 0, 0
  99.         for fl,desc in ECAPI.ripairs(floorDescs) do
  100.             preX, preY = term.getCursorPos()
  101.             floorLines[fl] = preY
  102.             local tag = ""
  103.             if (floorPass[fl] ~= nil) and (floorPass[fl] ~= "") then
  104.                 -- There IS a floor password.  Tag setting
  105.                 tag = "["..ECAPI.getConfigOption(CabinConfig,"PWTag").."] "
  106.                 --Should we or should we not print it?
  107.                 if (string.lower(ECAPI.getConfigOption(CabinConfig,"PWShow")) ~= "true") then
  108.                     -- assume DON'T
  109.                 else
  110.                     if Unlocked then ECAPI.printLine("|  "..ECAPI.padRight(fl,4,' ').." | "..ECAPI.padLeft(tag..desc,40,' ').."|") end
  111.                 end
  112.             else
  113.                 if Unlocked then ECAPI.printLine("|  "..ECAPI.padRight(fl,4,' ').." | "..ECAPI.padLeft(desc,40,' ').."|") end
  114.             end
  115.         end
  116.         if (preY < 15) then
  117.             --ElevatorControlAPI.printLine(divider)
  118.             for i = preY,15 do
  119.                 if Unlocked then ECAPI.printLine("|  "..ECAPI.padRight("",4,' ').." | "..ECAPI.padLeft("",40,' ').."|") end
  120.             end
  121.         end
  122.     else
  123.         if Unlocked then ECAPI.printLine("* No Floor computers registered. *") end
  124.     end
  125.     if Unlocked then ECAPI.printLine("") end
  126.     term.setCursorPos(12,18)
  127.     -- Any time we redraw the floors, we'll need to 'relocate' the cabin
  128.     ECAPI.broadcast(networkName(),'locate')
  129. end
  130.  
  131. function changeUpdate(output)
  132.     local oldX, oldY = term.getCursorPos()
  133.     term.setCursorPos(10,16)
  134.     if Unlocked then write(ECAPI.padLeft(output,40," ")) end
  135.     os.sleep(.25)
  136.     term.setCursorPos(10,16)
  137.     if Unlocked then write(ECAPI.padLeft(" ",40," ")) end
  138.     term.setCursorPos(oldX,oldY)
  139. end
  140.  
  141. local function updateFloor(floorID,indicator)
  142.     local oldX, oldY = term.getCursorPos()
  143.     for i = 6,15 do
  144.         term.setCursorPos(2,i)
  145.         if Unlocked then write("  ") end
  146.     end
  147.     if (floorLines ~= nil) and (ECAPI.table_count(floorLines) > 0) and (floorID ~= nil) then
  148.         term.setCursorPos(2,floorLines[tonumber(floorID)])
  149.         if Unlocked then write(indicator) end
  150.     end
  151.     term.setCursorPos(oldX, oldY)
  152. end
  153.  
  154. local function openDoor()
  155.     ECAPI.broadcast(networkName(),'openfloor')
  156. end
  157.  
  158. local function selectFloor(whichFloor)
  159.     ECAPI.broadcast(networkName(),'opendoor|invalid|') -- forces all doors closed
  160.     ECAPI.broadcast(networkName(),'request|'..whichFloor)
  161. end
  162.  
  163.  local function reconfig(args)
  164.     if (ECAPI.checkPassword(CabinScreen,CabinConfig,"ConfigPW")) then
  165.         local what = args[1]
  166.         if (what == nil) or (what == "") then
  167.             CabinConfig = DefaultConfig
  168.             createNewSettings()
  169.         else
  170.             what = ECAPI.caseCheck(CabinConfig,what)
  171.             if (args[2] == nil) then
  172.                 CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,what)
  173.             else
  174.                 CabinConfig = ECAPI.setConfigOption(CabinConfig,what,table.concat(args," ",2))
  175.             end
  176.             -- Make sure to SAVE changes
  177.             ECAPI.table_save(CabinConfig,cabinSettingsFile)
  178.            
  179.             ECAPI.openModem(modemSide())
  180.         end
  181.     else
  182.         justPrintLine("Invalid password.")
  183.     end
  184. end
  185.  
  186.  
  187. -- ######################################################
  188. -- ##  Settings Functions                              ##
  189. -- ######################################################
  190.  
  191. local function createNewSettings()
  192.  
  193.     CabinConfig = DefaultConfig
  194.     termClear()
  195.  
  196.     -- Confirm settings with the user, then save to file
  197.     CabinScreen = ECAPI.addPrintLine(CabinScreen,"No settings file found. Confirming settings.")
  198.  
  199.     -- To ensure this code plays nice with multiple elevators, Unique network names are required (as best as can)
  200.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Network")
  201.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Network")
  202.    
  203.     -- Confirm modem side
  204.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Modem")
  205.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Modem")
  206.  
  207.     -- Confirm Welcome message
  208.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Intro")
  209.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Intro")
  210.     -- Confirm First column heading
  211.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Floor")
  212.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Floor")
  213.     -- Confirm Second column heading
  214.     CabinScreen, CabinConfig = ECAPI.getConfigFromUser(CabinScreen,CabinConfig,"Description")
  215.     CabinScreen = ECAPI.printConfig(CabinConfig,CabinScreen,"Description")
  216.  
  217.        
  218.     -- Write to file
  219.     ECAPI.table_save(CabinConfig,cabinSettingsFile)
  220.     termClear()
  221. end
  222.  
  223. local function startupConfirmation()
  224.     -- Check if there's a settings file
  225.     if fs.exists(cabinSettingsFile) then
  226.         termClear()
  227.         CabinConfig = ECAPI.table_load(cabinSettingsFile)
  228.         ECAPI.verifyConfig(DefaultConfig,CabinConfig)
  229.         termClear()
  230.         CabinScreen = ECAPI.justPrintLine(CabinScreen,"Settings loaded.")
  231.         os.sleep(0.5)
  232.     else
  233.         createNewSettings()
  234.     end
  235.     ECAPI.openModem(modemSide())
  236.     if (ECAPI.getConfigOption(CabinConfig,"AccessPW") ~= "") then
  237.         Unlocked = false
  238.     end
  239. end
  240.  
  241.  
  242. -- ######################################################
  243. -- ##  Input Actions                                   ##
  244. -- ######################################################
  245.  
  246. -- MAX Topic details: 45 characters per table entry
  247. --                      |---------------------------------------------|
  248. local helpTopics = {
  249.     ["reboot"]      = { "Restart this terminal." ,},
  250.     ["clear"]       = { "Refresh the terminal screen." ,},
  251.     ["config"]      = { "Prints the current settings. Will not print",
  252.                         "any set passwords." ,},
  253.     ["reconfig"]    = { "With no parameters, re-run the whole setup.",
  254.                         "RECONFIG [option] to change a single setting",
  255.                         "Note: Reconfig can be password protected via",
  256.                         "the ConfigPW setting. If this password is",
  257.                         "lost, you will need server admin help or be",
  258.                         "forced to recreate the terminal." ,},
  259.     ["broadcast"]   = { "Manually broadcast <message>",},
  260.     ["send"]        = { "Manually send <id> <message>",},
  261.  
  262.     ["floors"]      = { "Print the usual cabin display"},
  263. }
  264.  
  265. local function printHelp(topic)
  266.     justPrintLine("Help on '"..string.upper(topic).."':")
  267.     local t = helpTopics[topic]
  268.     for _, text in ipairs(t) do
  269.         justPrintLine("  "..text)
  270.     end
  271. end
  272.  
  273. local commands = {
  274.     ["help"] = function (x)
  275.             if (x[1] ~= nil) then
  276.                 printHelp(x[1])
  277.             else
  278.                 justPrintLine("Please use HELP [COMMAND]. ? for Command List")
  279.             end
  280.         end,
  281.     ["reboot"] = function (x) os.reboot() end,
  282.     ["clear"] = function (x) termClear() end,
  283.     ["broadcast"] = function (x)
  284.             CabinScreen = justPrintInfo(CabinScreen,"REDNET",nil,nil,"Broadcast: "..table.concat(x," ",2))
  285.             ECAPI.broadcast(networkName(),table.concat(x," "))
  286.         end,
  287.     ["send"] = function (x)
  288.             CabinScreen = justPrintInfo(CabinScreen,"REDNET",nil,nil,"Send("..tonumber(x[1]).."): "..table.concat(x," ",2))
  289.             ECAPI.send(networkName(),tonumber(x[1]),table.concat(x," ",2))
  290.         end,
  291.    
  292.     ["config"] = function (x)
  293.             justPrintLine("Current Configuration:")
  294.             justPrintLine("-------------------------------")
  295.             ECAPI.printConfig(CabinConfig,CabinScreen)
  296.         end,
  297.     ["reconfig"] = function (x) reconfig(x) end,
  298.  
  299.     ["floors"] = function (x) printFloors() end,
  300.  
  301. }
  302.  
  303. local function printCommands()
  304.     local col = 1
  305.     local row = {}
  306.     for named, _ in pairs(commands) do
  307.         if (col < 5) then row[col] = string.upper(named) end
  308.         col = col + 1
  309.         if (col == 5) then
  310.             justPrintLine(ECAPI.padLeft(row[1],12," ")..ECAPI.padLeft(row[2],12," ")..ECAPI.padLeft(row[3],12," ")..ECAPI.padLeft(row[4],11," "))
  311.             row = {}
  312.             col = 1
  313.         end
  314.     end
  315.     if (col > 1) then
  316.         -- handles 'remainders'
  317.         justPrintLine(ECAPI.padLeft(row[1],12," ")..ECAPI.padLeft(row[2],12," ")..ECAPI.padLeft(row[3],12," ")..ECAPI.padLeft(row[4],11," "))
  318.     end
  319. end
  320.  
  321.  
  322. local function processCommands(input)
  323.     local arg = ECAPI.explode(" ",input)
  324.     local command = arg[1]
  325.     table.remove(arg,1)
  326.     if Unlocked then
  327.         if ECAPI.tableContainsKey(commands, command) then
  328.             commands[command](arg)
  329.         else
  330.             --validate the floor is in the list
  331.             if ECAPI.tableContainsKey(floorDescs,tonumber(command)) then
  332.                 if ECAPI.tableContainsKey(floorPass,tonumber(command)) then
  333.                     -- that floor is secure(ish)
  334.                     -- ask for the password
  335.                     local pwinput = ECAPI.getPasswordInput("Password:")
  336.                    
  337.                     -- check if it's right
  338.                     if (pwinput == ECAPI.decrypt(floorPass[tonumber(command)], networkName())) then
  339.                         changeUpdate(""..command.." selected.")
  340.                         selectFloor(command)
  341.                     else
  342.                         changeUpdate("Wrong PW!")
  343.                     end
  344.                 else
  345.                     changeUpdate(""..command.." selected.")
  346.                     selectFloor(command)
  347.                 end
  348.             else
  349.                 changeUpdate("Invalid selection.")
  350.             end
  351.         end
  352.     else
  353.         if ECAPI.checkPassword(CabinScreen,CabinConfig,"AccessPW") then
  354.             Unlocked = true
  355.             printFloors()
  356.         end
  357.     end
  358. end
  359.  
  360.  
  361. -- ######################################################
  362. -- ##  Handler Functions                               ##
  363. -- ######################################################
  364.  
  365. -- User input listener
  366. local function userConsole()
  367.     while KeepWaiting do
  368.         if Unlocked then
  369.             processCommands(ECAPI.getInput("Command:"))
  370.         else
  371.             if ECAPI.checkPassword(CabinScreen,CabinConfig,"AccessPW") then
  372.                 Unlocked = true
  373.                 relockAlarm = os.setAlarm(os.time()+2)
  374.                 printFloors()
  375.             end
  376.         end
  377.     end
  378. end
  379.  
  380. -- Rednet listener
  381. local function rednetListener()
  382.     while KeepWaiting do       
  383.         local sendID, rawmessage, distance = rednet.receive()
  384.         local packet = ECAPI.explode("|",rawmessage)
  385.         --print("MSG ["..sendID.."]: "..table.concat(packet,"|",2))
  386.         --os.sleep(3)
  387.         if packet[1] == networkName() then
  388.             if string.lower(packet[2]) ==     'floordata'       then
  389.                 printFloors(packet[3])
  390.             elseif string.lower(packet[2]) == 'reboot'          then
  391.                 os.reboot()
  392.             elseif string.lower(packet[2]) == 'displayfloor'           then
  393.                 justPrintLine('displayfloor: '..packet[3])
  394.                 updateFloor(tonumber(packet[3]),">>")
  395.                 --print("arrival")
  396.                 --os.sleep(1)  
  397.             elseif string.lower(packet[2]) == 'arrival'           then 
  398.                 updateFloor(tonumber(packet[3]),">>")
  399.             elseif string.lower(packet[2]) == 'displayup'           then
  400.                 --justPrintLine('displayup: '..packet[4])
  401.                 updateFloor(tonumber(packet[4]),packet[3])
  402.             elseif string.lower(packet[2]) == 'displaydown'           then
  403.                 --justPrintLine('displaydown: '..packet[4])
  404.                 updateFloor(tonumber(packet[4]),packet[3])
  405.             end
  406.         end
  407.     end
  408. end
  409.  
  410. local function relocker()
  411.     while KeepWaiting do
  412.         local evt,p1 = os.pullEvent("alarm")
  413.         if (relockAlarm ~= nil) and (p1 == relockAlarm) then
  414.             Unlocked = false
  415.             relockAlarm = nil
  416.         end
  417.     end
  418. end
  419.  
  420. -- ######################################################
  421. -- ##  Actual Run Program                              ##
  422. -- ######################################################
  423.  
  424. startupConfirmation()
  425. justPrintLine('Gathering floor information.')
  426. --os.sleep(4) -- startup delay to the network boot up
  427. -- get floors from network
  428. ECAPI.broadcast(networkName(),'getfloors')
  429. parallel.waitForAll(userConsole,rednetListener,relocker)
Advertisement
Add Comment
Please, Sign In to add comment