Advertisement
Rihlsul

ElevatorControl Cabin 1.01

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