Skip to content

Instantly share code, notes, and snippets.

@cheapie
Created April 18, 2017 00:57
Show Gist options
  • Save cheapie/a6f170d328f353c7c3a9e1f904c82171 to your computer and use it in GitHub Desktop.
Save cheapie/a6f170d328f353c7c3a9e1f904c82171 to your computer and use it in GitHub Desktop.
--Security Door Controller
--A product of Advanced Mesecons Devices, a Cheapie Systems company
--This is free and unencumbered software released into the public domain.
--See http://unlicense.org/ for more information
local tslib = {
_mt = {
setChannel = function(self,channel)
self._channel = channel
end,
getChannel = function(self)
return(self._channel)
end,
draw = function(self)
digiline_send(self._channel,self._commands)
end,
clear = function(self)
self._commands = {{command="clear"}}
end,
setLock = function(self,lock)
if lock then
table.insert(self._commands,{command="lock"})
else
table.insert(self._commands,{command="unlock"})
end
end,
addLabel = function(self,x,y,label,vertical)
assert((type(x))=="number","Invalid X position")
assert((type(y))=="number","Invalid Y position")
if type(label) ~= "string" then
label = tostring(label)
end
local cmd = {
command = "addlabel",
X = x,
Y = y,
label = label,
}
if vertical then cmd.command = "addvertlabel" end
table.insert(self._commands,cmd)
end,
addImage = function(self,x,y,w,h,tex)
assert((type(x))=="number","Invalid X position")
assert((type(y))=="number","Invalid Y position")
assert((type(w))=="number","Invalid width")
assert((type(h))=="number","Invalid height")
if type(tex) ~= "string" then
tex = tostring(tex)
end
local cmd = {
command = "addimage",
X = x,
Y = y,
W = w,
H = h,
texture_name = tex,
}
table.insert(self._commands,cmd)
end,
addButton = function(self,x,y,w,h,name,label,exit)
assert((type(x))=="number","Invalid X position")
assert((type(y))=="number","Invalid Y position")
assert((type(w))=="number","Invalid width")
assert((type(h))=="number","Invalid height")
if type(name) ~= "string" then
name = tostring(name)
end
if type(label) ~= "string" then
label = tostring(label)
end
local cmd = {
command = "addbutton",
X = x,
Y = y,
W = w,
H = h,
name = name,
label = label,
}
if exit then cmd.command = "addbutton_exit" end
table.insert(self._commands,cmd)
end,
addImageButton = function(self,x,y,w,h,name,label,tex,exit)
assert((type(x))=="number","Invalid X position")
assert((type(y))=="number","Invalid Y position")
assert((type(w))=="number","Invalid width")
assert((type(h))=="number","Invalid height")
if type(name) ~= "string" then
name = tostring(name)
end
if type(label) ~= "string" then
label = tostring(label)
end
if type(tex) ~= "string" then
tex = tostring(tex)
end
local cmd = {
command = "addimage_button",
X = x,
Y = y,
W = w,
H = h,
name = name,
label = label,
image = tex,
}
if exit then cmd.command = "addimage_button_exit" end
table.insert(self._commands,cmd)
end,
addField = function(self,x,y,w,h,name,label,default,password)
assert((type(x))=="number","Invalid X position")
assert((type(y))=="number","Invalid Y position")
assert((type(w))=="number","Invalid width")
assert((type(h))=="number","Invalid height")
if type(name) ~= "string" then
name = tostring(name)
end
if type(label) ~= "string" then
label = tostring(label)
end
if type(default) ~= "string" then
default = tostring(default)
end
local cmd = {
command = "addfield",
X = x,
Y = y,
W = w,
H = h,
name = name,
label = label,
default = default,
}
if password then cmd.command = "addpwdfield" end
table.insert(self._commands,cmd)
end,
addTextArea = function(self,x,y,w,h,name,label,default)
assert((type(x))=="number","Invalid X position")
assert((type(y))=="number","Invalid Y position")
assert((type(w))=="number","Invalid width")
assert((type(h))=="number","Invalid height")
if type(name) ~= "string" then
name = tostring(name)
end
if type(label) ~= "string" then
label = tostring(label)
end
if type(default) ~= "string" then
default = tostring(default)
end
local cmd = {
command = "addtextarea",
X = x,
Y = y,
W = w,
H = h,
name = name,
label = label,
default = default,
}
table.insert(self._commands,cmd)
end,
addDropdown = function(self,x,y,w,h,name,choices,selected)
assert((type(x))=="number","Invalid X position")
assert((type(y))=="number","Invalid Y position")
assert((type(w))=="number","Invalid width")
assert((type(h))=="number","Invalid height")
if not selected then selected = 1 end
assert((type(selected))=="number","Invalid selection index")
if type(name) ~= "string" then
name = tostring(name)
end
assert((type(choices) == "table" and #choices >= 1),"Invalid choices list")
local cmd = {
command = "adddropdown",
X = x,
Y = y,
W = w,
H = h,
name = name,
choices = choices,
selected_id = selected,
}
table.insert(self._commands,cmd)
end,
},
new = function(self,channel)
local ret = {}
for k,v in pairs(self._mt) do
ret[k] = v
end
ret._channel = channel
ret._commands = {{command="clear"}}
return ret
end,
}
local function isauthorized(checkname)
if type(checkname) ~= "table" then
checkname = {checkname}
end
for _,nametocheck in pairs(checkname) do
for _,name in pairs(mem.auth) do
if nametocheck == name then
return true
end
end
end
return false
end
local function pivot(tbl)
local ret = {}
for k,v in pairs(tbl) do
ret[v] = k
end
return ret
end
local function xor(a,b)
return((a or b) and not (a and b))
end
if event.type == "program" then
mem.players = {}
mem.auth = mem.auth or {"cheapie"}
mem.mode = "auto"
mem.screen = "main"
elseif event.channel == "detector" then
mem.players = event.msg
elseif event.channel == "settings" then
local fields = event.msg
if fields.inverseoff then mem.inverseout = false
elseif fields.inverseon then mem.inverseout = true
elseif fields.highsecoff then mem.highsec = false
elseif fields.highsecon then mem.highsec = true
elseif fields.open then mem.mode = "open"
elseif fields.closed then mem.mode = "closed"
elseif fields.auto then mem.mode = "auto"
elseif fields.adduser then
if fields.addusername and not isauthorized(fields.addusername) then
table.insert(mem.auth,fields.addusername)
end
elseif fields.deluser and #mem.auth > 0 then
table.remove(mem.auth,pivot(mem.auth)[fields.delusername])
end
elseif event.channel == "ui" then
local fields = event.msg
if mem.mode == "auto" and mem.screen == "main" and fields.request then
mem.screen = "checking"
interrupt(2,"checkauth")
end
elseif event.iid == "checkauth" then
if mem.highsec then
local authpresent = false
local unauthpresent = false
for _,name in pairs(mem.players) do
if isauthorized(name) then
authpresent = true
else
unauthpresent = true
end
end
if not authpresent then
mem.screen = "notauth"
elseif unauthpresent then
mem.screen = "highsec"
else
mem.screen = "granted"
mem.authorized = true
end
else
if isauthorized(mem.players) then
mem.authorized = true
mem.screen = "granted"
else
mem.screen = "notauth"
end
end
interrupt(5,"timeout")
elseif event.iid == "timeout" then
mem.authorized = false
if mem.mode == "auto" then mem.screen = "main" end
end
local settingsdisp = tslib:new("settings")
settingsdisp:setLock(true)
settingsdisp:addLabel(0,0,"DOOR SETTINGS")
settingsdisp:addField(0.3,1,2,1,"addusername","Add Authorized User","")
settingsdisp:addButton(2,0.75,1,1,"adduser","Add")
if #mem.auth > 0 then
settingsdisp:addDropdown(0,2,2,1,"delusername",mem.auth)
settingsdisp:addButton(2,1.9,1,1,"deluser","Remove")
else
settingsdisp:addLabel(0,2,"No Users")
end
if mem.inverseout then
settingsdisp:addImageButton(0,3,1,0.5,"inverseoff","","pipeworks_button_on.png")
else
settingsdisp:addImageButton(0,3,1,0.5,"inverseon","","pipeworks_button_off.png")
end
settingsdisp:addLabel(1,3,"Inverse Output (for piston doors)")
if mem.highsec then
settingsdisp:addImageButton(0,4,1,0.5,"highsecoff","","pipeworks_button_on.png")
else
settingsdisp:addImageButton(0,4,1,0.5,"highsecon","","pipeworks_button_off.png")
end
settingsdisp:addLabel(1,4,"High Security")
settingsdisp:addLabel(1,5.5,"Mode: "..string.upper(mem.mode))
settingsdisp:addButton(0,6,1,1,"open","OPEN")
settingsdisp:addButton(1.25,6,1,1,"auto","AUTO")
settingsdisp:addButton(2.5,6,1,1,"closed","CLOSED")
settingsdisp:draw()
local uidisp = tslib:new("ui")
uidisp:setLock(false)
if mem.mode == "open" then
uidisp:addLabel(0,0,"Door is being remotely held open")
elseif mem.mode == "auto" then
if mem.screen == "main" then
uidisp:addLabel(0,0,"Press button to request access")
uidisp:addButton(0,1,2,1,"request","Request Access")
elseif mem.screen == "checking" then
uidisp:addLabel(0,0,"Checking authorization...")
elseif mem.screen == "granted" then
uidisp:addLabel(0,0,"ACCESS GRANTED")
uidisp:addLabel(0,0.5,"You may now enter/exit")
elseif mem.screen == "notauth" then
uidisp:addLabel(0,0,"ACCESS DENIED")
uidisp:addLabel(0,0.5,"You are not authorized to use this door")
elseif mem.screen == "highsec" then
uidisp:addLabel(0,0,"ACCESS DENIED")
uidisp:addLabel(0,0.5,"A person not authorized to use the door is nearby")
end
elseif mem.mode == "closed" then
uidisp:addLabel(0,0,"Door has been remotely disabled")
end
uidisp:draw()
local out = xor(mem.mode == "open" or (mem.mode == "auto" and mem.authorized),mem.inverseout)
port = {a = out, b = out, c = out, d = out}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment