This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
GrayTheWolf's profile picture

Assertion failed; reading files from a disk

Started by GrayTheWolf, 13 October 2014 - 12:22 AM
GrayTheWolf #1
Posted 13 October 2014 - 02:22 AM
So this is for a locked door which reads the first line of the program on the disk with the name "passcode" and then sends the code to a central computer. The central computer then broadcasts a reply if that code is applicable to that door.

Anyway, this is the code from the client computer at one of the doors. It works great until someone puts a disk in that doesn't have the "passcode" program on it. I need to add in somehow to make the computer either ignore the disk or print an error or something. Right now it just says "assertion failed" when it can't find that program on the disk.



rednet.open("bottom")
function sendPass()
while true do
event = os.pullEvent("disk")
sFile = "disk/passcode"
hRead = assert(fs.open(sFile, "r"))
sPass = hRead.readLine()
hRead.close()
rednet.broadcast(sPass)
end
end
function open()
while true do
  local senderID,message,distance = rednet.receive()
if message == "1" then redstone.setOutput("left", true) disk.eject("top") sleep(3) redstone.setOutput("left", false) end
end
end
while true do
parallel.waitForAny(sendPass, open)
end
rednet.close("bottom")
Anavrins #2
Posted 13 October 2014 - 04:03 AM
Use fs.exists instead of assert.

Btw this can be done without the use of the parallel api, using os.pullEvent more efficiently.

local sFile = "/disk/passcode"
rednet.open("bottom")
while true do
  local event, sender, message ,distance = os.pullEvent() --// Use pullEventRaw here to prevent termination
  if event == "rednet_message" then
	if message == "1" then
	  redstone.setOutput("left", true)
	  disk.eject("top")
	  sleep(3)
	  redstone.setOutput("left", false)
	end
  elseif event == "disk" then
	if fs.exists(sFile) then
	  local hRead = fs.open(sFile,"r")
	  local sPass = hRead.readLine()
	  hRead.close()
	  rednet.broadcast(sPass)
	else printError("Passcode is absent from the disk")
	end
  end
end
Edited on 13 October 2014 - 02:10 AM
GrayTheWolf #3
Posted 13 October 2014 - 08:24 PM
Use fs.exists instead of assert.

Btw this can be done without the use of the parallel api, using os.pullEvent more efficiently.

local sFile = "/disk/passcode"
rednet.open("bottom")
while true do
  local event, sender, message ,distance = os.pullEvent() --// Use pullEventRaw here to prevent termination
  if event == "rednet_message" then
	if message == "1" then
	  redstone.setOutput("left", true)
	  disk.eject("top")
	  sleep(3)
	  redstone.setOutput("left", false)
	end
  elseif event == "disk" then
	if fs.exists(sFile) then
	  local hRead = fs.open(sFile,"r")
	  local sPass = hRead.readLine()
	  hRead.close()
	  rednet.broadcast(sPass)
	else printError("Passcode is absent from the disk")
	end
  end
end


That's great! Thanks!
GrayTheWolf #4
Posted 13 October 2014 - 09:14 PM
Another question, how would I go about making it check to see if a value exists in a table?


local users = {"2349", "8888", "1234"}

rednet.open("left")

while true do
  local senderID,message,distance = rednet.receive()
  if message == users then rednet.send(senderID, "1") end
  if message ~= users then rednet.send(senderID, "0") end
end

rednet.close("left")

This is the code from the host computer for the door system. I want it so that it will check if the received passcode is in the table, before it replies with a "1", and if the passcode isn't in the table it will just reply with a "0".
Edited on 13 October 2014 - 07:18 PM
Dragon53535 #5
Posted 13 October 2014 - 09:27 PM
Very simply put, you would need a loop to look through the table, the simplest for this is of course a for loop with pairs()


local function confirm(message,tbl)
  for key,value in pairs(tbl) do
	if value == message then
	  return true
	end
  end
  return false --#If it looks through the entire table and it wasn't there, then we return false
end
I make most of what i do into functions just so i can plug and use.

Inside your while loop at the bottom you can easily do this.

while true do
  local senderID,message,distance = rednet.receive()
  local con = confirm(message,users)
  if con then rednet.send(senderID,"1")
  elseif not con then rednet.send(senderID,"1") end
end
Edited on 13 October 2014 - 07:27 PM
Bomb Bloke #6
Posted 14 October 2014 - 12:46 AM
Bear in mind you can have the function return things other than true/false. Usually I'd make it return the key if the value is found; in this case it'd be easier to have it return "1" or "0".

There's also the option of making the values in your table the keys. This makes for shorter and faster running code:

local users = {["2349"] = "1", ["8888"] = "1", ["1234"] = "1"}

rednet.open("left")

while true do
  local senderID,message,distance = rednet.receive()
  rednet.send(senderID, users[message] or "0")
end

rednet.close("left")
GrayTheWolf #7
Posted 14 October 2014 - 07:31 PM
So I pulled from a few of the replies and I am here.


local users = {"2349", "8888", "1234"}
local clients = {"32", "37"}
rednet.open("left")
while true do
  local senderID,message,distance = rednet.receive()
  if senderID (is included in the table) clients and message (is included in the table) users then rednet.send(senderID, "1") end
end
rednet.close("left")


I would like it to just check the tables if the senderID is in the clients table and the recieved message is in the users table before it sends the "1" as a reply.
Bomb Bloke #8
Posted 15 October 2014 - 12:16 AM
Well, let's take the code Dragon gave you and use it like he showed you:

local function confirm(message,tbl)
  for key,value in pairs(tbl) do
    if value == message then
      return true
    end
  end
  return false --#If it looks through the entire table and it wasn't there, then we return false
end

local users = {"2349", "8888", "1234"}
local clients = {32, 37}  -- senderIDs are received as numbers, not as strings.
rednet.open("left")
while true do
  local senderID,message,distance = rednet.receive()
  if confirm(senderID, clients) and confirm(message, users) then rednet.send(senderID, "1") end
end
rednet.close("left")