Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- File usage:
- --
- -- Just copy and paste this code on to some random file on a disk and create another startup file named "startup" on that disk.
- -- In "startup" put (replace [NAME] with the filename you put this code into)
- -- os.loadAPI("disk/[NAME]")"
- --
- -- Note if using Encryption: If you plan to use this code on different machines, BUT you want to use the an RFID card between them
- -- (you have one machine for reading and one for writing), you MUST MUST MUST use the same disk, OR copy the
- -- "key-Blowfish" file to every other disk you want to use with that RFID card with
- --
- -- Free software license: I am posting this under the GNU GPL (GNU General Public License), that is to say, you can
- -- take this code and do whatever you want with it, but if you distrubte it, you must also do so under the GNU GPL.
- --
- -- I also ask you give credit to me as the original writer
- --
- -- --Angellus_Mortis
- --
- -- Returns a handle to a peripheral connect of a specificed type
- -- Returns nil if peripheral of type is not found
- -- Input:
- -- type (string) : type of peripheral to return a handle for
- local function getPeripheral(type)
- local sides = {"top", "bottom", "left", "right", "back"}
- local i = 1
- repeat
- if peripheral.getType(sides[i]) == type then
- return peripheral.wrap(sides[i])
- end
- i = i + 1
- until i == 6
- return nil
- end
- -- Changes the color to write a quick message and then changes it back
- -- Only changes color if term is in color
- -- Input:
- -- text (string) : text to output in color
- -- someColor (color) : color to output the text in
- local function writeColorMessage(text, someColor)
- if term.isColor() then
- term.setTextColor(someColor)
- end
- term.write(text)
- if term.isColor() then
- term.setTextColor(colors.white)
- end
- end
- -- Callback for when scanning starts from reader
- -- By default,
- -- this looks for an attached montior (should be 2x1)
- -- And just displays "ID Required"
- -- Changes background to Cyan and text to black
- -- Turns off signal to door (see onValidCard for more)
- local function onScanStart()
- local screen = getPeripheral("monitor")
- -- turn off door signal
- redstone.setBundledOutput("top", 0)
- if not screen then
- -- Throw error to console if monitor was not found
- writeColorMessage("Error: ", colors.red)
- term.write("No Monitor Detected!")
- print()
- else
- -- Write message
- screen.setTextScale(1.8)
- screen.clear()
- screen.setCursorPos(1, 2)
- if screen.isColor() then
- screen.setTextColor(colors.black)
- screen.setBackgroundColor(colors.cyan)
- end
- screen.write("ID Required")
- end
- end
- -- Callback when an invalid card is thown from Reader
- -- By default,
- -- this looks for an attached montior (should be 2x1)
- -- And just displays "ID Required" in black
- -- displays "Not Authorized!" in red
- -- Cyan background
- local function onInvalidCard()
- local screen = getPeripheral("monitor")
- -- Throw error to console if monitor was not found
- if not screen then
- writeColorMessage("Error: ", colors.red)
- term.write("No Monitor Detected!")
- print()
- else
- -- Write message
- screen.setTextScale(1.4)
- screen.clear()
- screen.setCursorPos(4, 2)
- if screen.isColor() then
- screen.setTextColor(colors.black)
- screen.setBackgroundColor(colors.cyan)
- end
- screen.write("ID Required")
- screen.setCursorPos(3, 4)
- if screen.isColor() then
- screen.setTextColor(colors.red)
- end
- screen.write("Not Authorized!")
- end
- end
- -- Callback for when valid card is thrown from reader
- -- By default,
- -- this looks for an attached montior (should be 2x1)
- -- And just displays "ID Required" in black
- -- displays "Access Granted" in green
- -- Cyan background
- --
- -- Sends white wire signal on top of the monitor
- -- To set up a door lock, just connect a white wire to the top
- -- then connect the wire to a door.
- -- Also set up monitor so the user knows what is going on
- local function onValidCard()
- local screen = getPeripheral("monitor")
- -- Throw error to console if monitor was not found
- if not screen then
- writeColorMessage("Error: ", colors.red)
- term.write("No Monitor Detected!")
- print()
- else
- -- Write message
- screen.setTextScale(1.4)
- screen.clear()
- screen.setCursorPos(4, 2)
- if screen.isColor() then
- screen.setTextColor(colors.black)
- screen.setBackgroundColor(colors.cyan)
- end
- screen.write("ID Required")
- screen.setCursorPos(3, 4)
- if screen.isColor() then
- screen.setTextColor(colors.green)
- end
- screen.write("Access Granted")
- --Open door
- redstone.setBundledOutput("top", 1)
- end
- end
- -- Global varibles
- local data = {["useEncryption"] = true, ["encryptionType"] = "Blowfish", ["keySize"] = nil}
- -- test if the frist character of a given string is the one supplied
- -- Input:
- -- testString (string) : character to test for (only ONE character)
- -- inputString (string) : string to test against
- local function checkFirstChar(testString, inputString)
- if string.lower(testString) == string.lower(string.sub(inputString, 1, 1)) then
- return true
- else
- return false
- end
- end
- -- Prints program header
- -- Input:
- -- isAdmin (bool) : whether or not program is in admin mode
- local function header(isAdmin, type)
- local title
- if not type then
- title = "RFID Writer/Reader"
- elseif type == "writer" then
- title = "RFID Writer"
- elseif type == "reader" then
- title = "RFID Reader"
- end
- term.clear()
- term.setCursorPos(1, 1)
- if isAdmin then
- writeColorMessage(title .. " - Admin Mode", colors.green)
- print()
- else
- writeColorMessage(title, colors.cyan)
- print()
- end
- print()
- end
- -- Returns a string of the encryption key to use to encrypt the RFID text with
- -- Input:
- -- encryptor (handle) : handle to cryptographic accelerator
- local function getKey(encryptor)
- local file = fs.open("disk/key-"..data["encryptionType"], "r")
- -- If the key has not been generated yet, generate it
- if not file then
- file = fs.open("disk/key-"..data["encryptionType"], "w")
- local key = encryptor.generateSymmetricKey(data["encryptionType"], data["keySize"])
- local keyEnc = key.encode()
- file.write(keyEnc)
- file.close()
- return keyEnc
- end
- local key = file.readLine()
- file.close()
- return key
- end
- -- Determines if text needs decrypted and then returns it
- -- Input:
- -- message (string) : text possibly decrypted
- -- encryptor (handle) : handle to cryptographic accelerator
- local function testForEncryption(message, encryptor)
- -- If using encryption..
- if data["useEncryption"] and encryptor then
- local key = encryptor.decodeKey(data["encryptionType"], getKey(encryptor))
- -- Attempt to decrypt the message
- local status, err = pcall(function() message = key.decrypt(data["encryptionType"], message) end)
- -- If failes, set message to empty string to force password check to fail
- if not status then
- message = ""
- end
- end
- return message
- end
- -- Determines if text needs to be encrypted or not and then returns it
- -- Input:
- -- text (string) : text to be written
- -- encryptor (handle) : handle to cryptographic accelerator
- local function testEncode(text, encryptor)
- if data["useEncryption"] and encryptor then
- -- Convert the string into an object
- local key = encryptor.decodeKey(data["encryptionType"], getKey(encryptor))
- text = key.encrypt(data["encryptionType"], text)
- end
- return text
- end
- local function resetScreen()
- term.setCursorPos(1,1)
- term.clear()
- end
- -- Main program for the writer
- -- Input:
- -- param (string) : optional parameter for admin mode
- function Writer(param)
- -- Writing Variables
- local label
- local text
- local writer = getPeripheral("rfid writer")
- -- Encryption vars
- local encryptor = getPeripheral("cryptographic accelerator")
- -- Admin related vars
- local admin = false
- local secretParam = '146790'
- -- Simply delete the password if you want to prompt the user for it
- local adminPassword = ''
- -- Test if admin is to run
- if param == secretParam then
- admin = true
- -- If auto mode is off, ask for admin password
- if (adminPassword == '') then
- header(true, "writer")
- term.write("Enter the admin password: ")
- if term.isColor() then
- term.setTextColor(colors.cyan)
- end
- adminPassword = read("*")
- if term.isColor() then
- term.setTextColor(colors.white)
- end
- end
- end
- -- If RFID writer is not connected
- while not writer do
- header(admin, "writer")
- term.write("No RFID Writer Connected! ")
- writeColorMessage(":(", colors.red)
- print()
- term.write("Please connect one and press ")
- writeColorMessage("ENTER", colors.green)
- print()
- local event, param1
- repeat
- event, param1 = os.pullEvent ("key")
- until param1 == 28
- writer = getPeripheral("rfid writer")
- end
- -- If no valid card is present
- while (not writer.isPresent()) or writer.isCoded() do
- header(admin, "writer")
- term.write("RFID Card is either missing or already coded ")
- writeColorMessage(":(", colors.red)
- print()
- term.write("Please insert a blank RFID card and press ")
- writeColorMessage("ENTER", colors.green)
- print()
- local event, param1
- repeat
- event, param1 = os.pullEvent ("key")
- until param1 == 28
- end
- header(admin, "writer")
- -- Set Disk Label
- term.write("Enter the label for the disk: ")
- if term.isColor() then
- term.setTextColor(colors.cyan)
- end
- label = read()
- if term.isColor() then
- term.setTextColor(colors.white)
- end
- if label == secretParam then
- return Writer(label)
- end
- -- Gets text to encode
- term.write("Enter text to write to RFID Card: ")
- if term.isColor() then
- term.setTextColor(colors.cyan)
- end
- text = read()
- if term.isColor() then
- term.setTextColor(colors.white)
- end
- -- Y-offset for any admin mode related messages
- local offset = 0
- print()
- print("Starting RFID Encoding...")
- if not admin then
- -- Encodes card
- writer.encode(testEncode(text, encryptor), label)
- else
- -- Passes in admin password
- writer.encode(testEncode(text, encryptor), label, adminPassword)
- -- Does not really test. Uses progress to determine if the password was successful
- term.write("Testing admin password...")
- offset = offset + 1
- end
- os.sleep(1)
- local progress = writer.getProgress()
- -- if Admin mode, display if password was successful
- if progress >= 0 and admin then
- offset = offset + 1
- term.write("..Invalid!")
- print()
- -- turn off admin mode so progress bar will show
- admin = false
- elseif admin then
- term.write("..Success")
- print()
- print()
- end
- -- if not admin mode (or password failed) show progress bar
- if not admin then
- term.setCursorPos(1, 8 + offset)
- local toDraw = 1
- -- adjust for varible screen width
- local w = term.getSize() - 10
- local frac = 1 / w
- -- Draw empty progress bar
- term.write("0% [")
- term.setCursorPos(5 + w, 8 + offset)
- term.write("] 100%")
- -- Draw progress line
- while progress >= 0 do
- term.setCursorPos(4 + toDraw, 8 + offset)
- while progress >= (toDraw * frac) do
- term.write("-")
- toDraw = toDraw + 1
- end
- os.sleep(1)
- progress = writer.getProgress()
- end
- -- make sure progress bar gets filled ;)
- while (toDraw * frac) <= 1 do
- term.write("-")
- toDraw = toDraw + 1
- end
- print()
- end
- print("Text successfully written to card.")
- print()
- term.write("Press ")
- writeColorMessage("ENTER", colors.green)
- term.write(" to exit...")
- local event, param1
- repeat
- event, param1 = os.pullEvent ("key")
- until param1 == 28
- resetScreen()
- Writer()
- end
- -- Main program for the reader
- function Reader()
- -- Reading Varibles
- local reader = getPeripheral("rfid reader")
- local allowOtherCards = false
- local detected = 0
- local valid = false
- local password = ""
- -- Encryption vars
- local encryptor = getPeripheral("cryptographic accelerator")
- -- If RFID reader is not connected
- while not reader do
- header(false, "reader")
- print("No RFID Reader Connected! :(")
- term.write("Please connect one and press ")
- writeColorMessage("ENTER", colors.green)
- print()
- local event, param1
- repeat
- event, param1 = os.pullEvent ("key")
- until param1 == 28
- reader = getPeripheral("rfid reader")
- end
- -- If password is not set, prompt user to provide a card with one on it
- -- IMPORTANT! Only one RFID card can be present when setting password or else
- -- the wrong password may be set
- while password == "" do
- header(false, "reader")
- print("Password not set. Verify the card with the valid ")
- print("password on it is in range and is the ONLY card ")
- term.write("within range and press ")
- writeColorMessage("ENTER", colors.green)
- print()
- local event, param1
- repeat
- event, param1 = os.pullEvent ("key")
- until param1 == 28
- print()
- print("Scanning for card...")
- reader.scan()
- -- Repeat pull event until done scanning
- repeat
- event, param1 = os.pullEvent()
- if (event == "rfid_detected") then
- print("Card found. Trying to set password...")
- password = testForEncryption(param1, encryptor)
- if not (password == "") then
- -- Some stuff for the user
- print("Password set")
- print("Starting reader...")
- sleep(1)
- end
- -- Could not set password
- elseif event == "rfid_scan_done" and password == "" then
- if data["useEncryption"] then
- print("No card found or unable to decrypt password!")
- print()
- print("Make sure you are using the same encryption key for the reader and writer.")
- sleep(5)
- else
- print("No card found!")
- sleep(2)
- end
- end
- until event == "rfid_scan_done" or not (password == "")
- end
- -- ASk the user if they want to still throw a valid card event when there
- -- are other invalid cards around
- local doRepeat = true
- repeat
- header(false, "reader")
- print("Do you want to throw valid card with other invalid cards around?")
- term.write("Enter yes/[no]: ")
- if term.isColor() then
- term.setTextColor(colors.cyan)
- end
- local usrInp = read()
- if term.isColor() then
- term.setTextColor(colors.white)
- end
- if checkFirstChar('n', usrInp) or usrInp == '' then
- allowOtherCards = false
- doRepeat = false
- elseif checkFirstChar('y', usrInp) then
- allowOtherCards = true
- doRepeat = false
- end
- until not doRepeat
- -- Start reading loop
- while true do
- header(false, "reader")
- valid = false
- detected = 0
- print("Scanning for cards...")
- print()
- reader.scan()
- onScanStart()
- local event, message
- repeat
- event, message = os.pullEvent()
- if event == "rfid_detected" then
- print("An RFID Card was detected.")
- term.write("Testing password...")
- if testForEncryption(message, encryptor) == password then
- term.write("..Success")
- if ((not allowOtherCards) and detected == 0) or allowOtherCards then
- valid = true
- end
- else
- term.write("..Invalid")
- if not allowOtherCards then
- valid = false
- end
- end
- print()
- print()
- detected = detected + 1
- end
- until event == "rfid_scan_done"
- if detected == 0 then
- print("No cards found.")
- elseif valid then
- print("Valid password!")
- onValidCard()
- elseif not allowOtherCards then
- print("Invalid password or other cards nearby!")
- onInvalidCard()
- else
- print("Invalid password!")
- onInvalidCard()
- end
- os.sleep(5)
- end
- Reader()
- end
- function runRFID()
- local reader = getPeripheral("rfid reader")
- local writer = getPeripheral("rfid writer")
- -- If RFID writer/reader is not connected
- while not reader and not writer do
- header(false)
- print("No RFID Writer/Reader Connected! :(")
- term.write("Please connect one and press ")
- writeColorMessage("ENTER", colors.green)
- print()
- local event, param1
- repeat
- event, param1 = os.pullEvent ("key")
- until param1 == 28
- reader = getPeripheral("rfid reader")
- writer = getPeripheral("rfid writer")
- end
- if reader and writer then
- local doRepeat = true
- repeat
- header(false)
- print("Both a reader and writer connected.")
- term.write("Enter [reader]/writer: ")
- if term.isColor() then
- term.setTextColor(colors.cyan)
- end
- local usrInp = read()
- if term.isColor() then
- term.setTextColor(colors.white)
- end
- if checkFirstChar('r', usrInp) or usrInp == '' then
- Reader()
- doRepeat = false
- elseif checkFirstChar('w', usrInp) then
- Writer()
- doRepeat = false
- end
- until not doRepeat
- elseif reader then
- Reader()
- elseif writer then
- Writer()
- end
- end
- function startup()
- local reader = getPeripheral("rfid reader")
- local writer = getPeripheral("rfid writer")
- local encryptor = getPeripheral("cryptographic accelerator")
- header(false)
- writeColorMessage("Booting.", colors.magenta)
- sleep(1)
- writeColorMessage(".", colors.magenta)
- sleep(1)
- writeColorMessage(".", colors.magenta)
- print()
- if encryptor then
- writeColorMessage("Encryptor found", colors.cyan)
- print()
- print("Using encryption...")
- data["useEncryption"] = true
- else
- writeColorMessage("No encryptor found", colors.red)
- print()
- print("Turning off encryption...")
- data["useEncryption"] = false
- end
- sleep(1)
- if not reader and not writer then
- writeColorMessage("Reader and writer missing", colors.red)
- print()
- print("Prompting to place one...")
- elseif reader and writer then
- writeColorMessage("Reader ", colors.green)
- term.write("and ")
- writeColorMessage("Writer ", colors.yellow)
- term.write("both found")
- print()
- print("Prompting which to use...")
- elseif reader then
- writeColorMessage("Reader found", colors.green)
- print()
- print("Starting reader...")
- elseif writer then
- writeColorMessage("Writer found", colors.yellow)
- print()
- print("Starting writer...")
- end
- sleep(1)
- runRFID()
- end
- function os.pullEvent(_sFilter)
- local event = { os.pullEventRaw(_sFilter) }
- if event[1] == "terminate" then
- runRFID()
- end
- return unpack(event)
- end
- startup()
Advertisement
Add Comment
Please, Sign In to add comment