Skip to content

Instantly share code, notes, and snippets.

@cheapie
Created July 27, 2023 03:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cheapie/60945927d38c78cb7a81b1554f167381 to your computer and use it in GitHub Desktop.
Save cheapie/60945927d38c78cb7a81b1554f167381 to your computer and use it in GitHub Desktop.
local techage = require("techage")
local is_button = {}
if mem.params then for k,v in ipairs(mem.params.button_ids) do is_button[v] = k end end
local function getnextcallabove()
if mem.actpos == mem.params.num_floors then return end
for i=mem.actpos,mem.params.num_floors,1 do
if mem.queue[i] then return i end
end
end
local function getnextcallbelow()
if mem.actpos == 1 then return end
for i=mem.actpos,1,-1 do
if mem.queue[i] then return i end
end
end
local function calc_move(act,des)
local movelen = 0
if act<des then
for i=act,des-1,1 do
movelen = movelen+mem.params.distance_above[i]
end
elseif act>des then
for i=des,act-1,1 do
movelen = movelen-mem.params.distance_above[i]
end
end
return movelen
end
local function open()
if mem.state ~= "idle" then return end --Yes, that's the door lock. I'm sure it meets safety standards.
mem.state = "opening"
interrupt(3,"opened")
local doors = mem.params.door_ids[mem.actpos]
for _,v in ipairs(doors) do
techage.send(v,"a2b")
end
end
local function close()
if mem.state ~= "open" then return end
mem.state = "closing"
interrupt(3,"closed")
local doors = mem.params.door_ids[mem.actpos]
for _,v in ipairs(doors) do
techage.send(v,"b2a")
end
end
local function go()
if mem.despos == mem.actpos then return end
if mem.state ~= "idle" then return end
mem.state = "moving"
local distance = calc_move(mem.actpos,mem.despos)
techage.send(mem.params.hoist_id,"move2",string.format("0,%d,0",distance))
interrupt(0.5,"checkhoist")
end
local function handle_call()
local nextup = getnextcallabove()
local nextdn = getnextcallbelow()
if mem.dir == "up" then
if nextup then
mem.despos = nextup
elseif nextdn then
mem.dir = "down"
mem.despos = nextdn
end
elseif mem.dir == "down" then
if nextdn then
mem.despos = nextdn
elseif nextup then
mem.dir = "up"
mem.despos = nextup
end
end
if mem.despos ~= mem.actpos then
go()
elseif mem.queue[mem.actpos] and mem.state == "idle" then
open()
mem.queue[mem.actpos] = nil
end
end
local function termparse(text)
if text == "" and mem.termstate ~= "status" then return end
local comma = string.find(text,",",nil,true)
local cmd = comma and string.upper(string.sub(text,1,comma-1)) or string.upper(text)
local remain = ""
if comma then
remain = string.sub(text,comma+1,-1)
end
if cmd == "CC" then
mem.termstate = "carcall"
elseif mem.termstate == "status" then
mem.termstate = "mainmenu"
if text ~= "" then termparse(text) end
elseif mem.termstate == "mainmenu" then
if cmd == ".." or cmd == "ST" then
mem.termstate = "status"
elseif cmd == "SY" then
mem.termstate = "system_commands"
elseif cmd == "AD" then
mem.termstate = "adjustments"
end
elseif mem.termstate == "system_commands" then
mem.extraspace = not mem.extraspace
if cmd == ".." then
mem.termstate = "mainmenu"
elseif cmd == "OP" then
if mem.state == "idle" then open() end
elseif cmd == "CL" then
if mem.state == "open" then interrupt(0,"close") end
elseif cmd == "CA" then
mem.termstate = "carcall"
end
elseif mem.termstate == "adjustments" then
if cmd == ".." then
mem.termstate = "mainmenu"
elseif cmd == "FL" then
mem.termstate = "floortable"
elseif cmd == "BU" then
mem.termstate = "buttonids"
elseif cmd == "DO" then
mem.termstate = "doorids"
elseif cmd == "MO" then
mem.termstate = "hoistid"
elseif cmd == "RE" then
mem.termstate = "relearn"
end
elseif mem.termstate == "floortable" then
if cmd == ".." then
mem.termstate = "adjustments"
elseif cmd == "AD" then
mem.termstate = "addfloor"
elseif cmd == "ED" then
mem.termstate = "editheight"
elseif cmd == "RE" then
mem.termstate = "removefloor"
end
elseif mem.termstate == "addfloor" then
local height = tonumber(cmd)
if height then
if height == math.floor(height) and height > 0 and height < 200 then
mem.params.num_floors = mem.params.num_floors+1
mem.params.distance_above[mem.params.num_floors-1] = height
mem.params.door_ids[mem.params.num_floors] = {}
mem.termstate = "floortable"
end
else
mem.termstate = "floortable"
end
elseif mem.termstate == "editheight" then
local floor = tonumber(cmd)
if floor then
if floor == math.floor(floor) and floor > 0 and floor < mem.params.num_floors then
mem.editingfloor = floor
mem.termstate = "editheight2"
end
else
mem.termstate = "floortable"
end
elseif mem.termstate == "editheight2" then
local height = tonumber(cmd)
if height then
if height == math.floor(height) and height > 0 and height < 200 then
mem.params.distance_above[mem.editingfloor] = height
mem.termstate = "floortable"
end
else
mem.termstate = "floortable"
end
elseif mem.termstate == "removefloor" then
local floor = tonumber(cmd)
if floor then
if floor == math.floor(floor) and floor > 0 and floor <= mem.params.num_floors then
if floor < mem.params.num_floors then table.remove(mem.params.distance_above,floor) end
table.remove(mem.params.door_ids,floor)
mem.params.num_floors = mem.params.num_floors-1
mem.termstate = "floortable"
end
else
mem.termstate = "floortable"
end
elseif mem.termstate == "hoistid" then
local id = tonumber(cmd)
if id then
if id == math.floor(id) and id >= 0 then
mem.params.hoist_id = id
mem.termstate = "adjustments"
end
else
mem.termstate = "adjustments"
end
elseif mem.termstate == "buttonids" then
if cmd == ".." then
mem.termstate = "adjustments"
elseif cmd == "AD" then
mem.termstate = "addbutton"
elseif cmd == "RE" then
mem.termstate = "removebutton"
end
elseif mem.termstate == "addbutton" then
local id = tonumber(cmd)
if id then
if id == math.floor(id) and id >= 0 then
if not is_button[id] then
table.insert(mem.params.button_ids,id)
end
mem.termstate = "buttonids"
end
else
mem.termstate = "buttonids"
end
elseif mem.termstate == "removebutton" then
local id = tonumber(cmd)
if id then
if id == math.floor(id) and id >= 0 then
if is_button[id] then
table.remove(mem.params.button_ids,is_button[id])
end
mem.termstate = "buttonids"
end
else
mem.termstate = "buttonids"
end
elseif mem.termstate == "doorids" then
local floor = tonumber(cmd)
if floor then
if floor == math.floor(floor) and floor > 0 and floor <= mem.params.num_floors then
mem.editingfloor = floor
mem.termstate = "doorids2"
end
else
mem.termstate = "adjustments"
end
elseif mem.termstate == "doorids2" then
if cmd == ".." then
mem.termstate = "adjustments"
elseif cmd == "AD" then
mem.termstate = "adddoor"
elseif cmd == "RE" then
mem.termstate = "removedoor"
end
elseif mem.termstate == "adddoor" then
local is_door = {}
for k,v in ipairs(mem.params.door_ids[mem.editingfloor]) do
is_door[v] = k
end
local id = tonumber(cmd)
if id then
if id == math.floor(id) and id >= 0 then
if not is_door[id] then
table.insert(mem.params.door_ids[mem.editingfloor],id)
end
mem.termstate = "doorids2"
end
else
mem.termstate = "doorids2"
end
elseif mem.termstate == "removedoor" then
local is_door = {}
for k,v in ipairs(mem.params.door_ids[mem.editingfloor]) do
is_door[v] = k
end
local id = tonumber(cmd)
if id then
if id == math.floor(id) and id >= 0 then
if is_door[id] then
table.remove(mem.params.door_ids[mem.editingfloor],is_door[id])
end
mem.termstate = "doorids2"
end
else
mem.termstate = "doorids2"
end
elseif mem.termstate == "carcall" then
mem.extraspace = not mem.extraspace
local floor = tonumber(cmd)
if floor then
if floor == math.floor(floor) and floor > 0 and floor <= mem.params.num_floors then
if mem.actpos == floor and mem.state == "idle" then
open()
else
mem.queue[floor] = true
if mem.state == "idle" then
handle_call()
elseif mem.state == "open" then
interrupt(0,"close")
end
end
mem.termstate = "system_commands"
end
else
mem.termstate = "system_commands"
end
end
if comma then termparse(remain) end
end
if event.type == "program" then
mem.actpos = 1
mem.despos = 1
mem.state = "idle"
mem.queue = {}
mem.dir = "up"
mem.termstate = "status"
if not mem.params then
mem.params = {
num_floors = 1,
distance_above = {},
button_ids = {},
door_ids = {{}},
hoist_id = -1,
}
end
techage.init()
elseif event.channel and string.sub(event.channel,1,8) == "techage_" and is_button[tonumber(string.sub(event.channel,9,-1))] then
local callpos = tonumber(event.msg.message)
if event.msg.message == "open" and mem.state == "idle" then
open()
elseif callpos then
mem.queue[callpos] = (mem.actpos ~= callpos) or (mem.state ~= "open")
if mem.state == "idle" then
handle_call()
elseif mem.state == "open" then
interrupt(callpos == mem.actpos and 8 or 0,"close")
end
end
elseif event.iid == "checkdoors" then
techage.send(mem.params.door_ids[mem.actpos][1],"state")
elseif event.channel and event.channel==string.format("techagereply_%d",mem.params.door_ids[mem.actpos][1]) and mem.state == "opening" then
if event.msg == "stopped" then
interrupt(0.25,"opened")
else
interrupt(0.25,"checkdoors")
end
elseif event.channel and event.channel==string.format("techagereply_%d",mem.params.door_ids[mem.actpos][1]) and mem.state == "closing" then
if event.msg == "stopped" then
interrupt(0.25,"closed")
else
interrupt(0.25,"checkdoors")
end
elseif event.iid == "opened" and mem.state == "opening" then
mem.state = "open"
interrupt(8,"close")
elseif event.iid == "closed" and mem.state == "closing" then
mem.state = "idle"
handle_call()
elseif event.iid == "close" and mem.state == "open" then
close()
elseif event.iid == "checkhoist" and mem.state == "moving" then
techage.send(mem.params.hoist_id,"state")
elseif event.channel and event.channel==string.format("techagereply_%d",mem.params.hoist_id) then
if event.msg == "stopped" then
mem.actpos = mem.despos
mem.state = "idle"
mem.queue[mem.actpos] = nil
open()
else
interrupt(0.5,"checkhoist")
end
elseif event.type == "terminal" then
termparse(event.text)
end
clearterm()
if mem.termstate == "status" then
local date = os.datetable()
print("GREAPIE MINECONIC VM "..string.format("%04d-%02d-%02d %02d:%02d:%02d",date.year,date.month,date.day,date.hour,date.min,date.sec))
print()
print()
print()
for i=mem.params.num_floors,1,-1 do
local car = (mem.queue[i] and " * " or " ")
if mem.actpos == i then
if mem.state == "opening" then
car = "[< >]"
elseif mem.state == "closing" then
car = "[> <]"
elseif mem.state == "open" then
car = "[ ]"
else
car = "[ | ]"
end
end
print(string.format(" %02d |%s| %02d",i,car,i))
end
print()
print(string.format(" POS %02d POS",mem.actpos))
print(string.format(" DRV %02d DRV",mem.despos))
elseif mem.termstate == "mainmenu" then
print("MAIN MENU")
print()
print("* SYSTEM COMMANDS")
print()
print("* ADJUSTMENTS")
print()
print("* STATUS")
print()
print("]")
elseif mem.termstate == "system_commands" then
print("SYSTEM COMMANDS")
print((mem.extraspace and " " or ""))
print("* CAR CALL")
print()
print("* OPEN DOORS")
print()
print("* CLOSE DOORS")
print()
print("]")
elseif mem.termstate == "adjustments" then
print("ADJUSTMENTS")
print()
print("* FLOOR TABLE")
print()
print("* BUTTON IDS")
print()
print("* DOOR IDS")
print()
if mem.params.hoist_id >= 0 then
print("* MOTOR ID: "..tostring(mem.params.hoist_id))
else
print("* MOTOR ID: --")
end
print()
print("]")
elseif mem.termstate == "floortable" then
print("FLOOR TABLE")
print()
for i=mem.params.num_floors,1,-1 do
if i == mem.params.num_floors then
print(string.format("%d: HEIGHT -",i))
else
print(string.format("%d: HEIGHT %d",i,mem.params.distance_above[i]))
end
end
print()
print("* ADD FLOOR")
print()
print("* EDIT HEIGHT")
print()
print("* REMOVE FLOOR")
print()
print("]")
elseif mem.termstate == "editheight" or mem.termstate == "removefloor" then
print()
print("FLOOR NUMBER?")
print("]")
elseif mem.termstate == "addfloor" then
print()
print("HEIGHT OF PREVIOUS FLOOR?")
print("]")
elseif mem.termstate == "editheight2" then
print()
print("FLOOR HEIGHT?")
print("]")
elseif mem.termstate == "hoistid" then
print()
print("MOTOR ID?")
print("]")
elseif mem.termstate == "buttonids" then
print("BUTTON IDS")
print()
if #mem.params.button_ids > 0 then
local linecount = #mem.params.button_ids%10+1
for i=1,linecount,1 do
local line = ""
local start = (i-1)*10+1
for j=start,start+9,1 do
if j <= #mem.params.button_ids then
line = line..tostring(mem.params.button_ids[j])..", "
end
end
if string.len(line) > 2 then
print(string.sub(line,1,-3))
end
end
else
print("NONE")
end
print()
print("* ADD BUTTON")
print()
print("* REMOVE BUTTON")
print()
print("]")
elseif mem.termstate == "addbutton" or mem.termstate == "removebutton" then
print()
print("BUTTON ID?")
print("]")
elseif mem.termstate == "doorids" then
print()
print("FLOOR NUMBER?")
print("]")
elseif mem.termstate == "doorids2" then
print("DOOR IDS - FLOOR "..tostring(mem.editingfloor))
print()
if #mem.params.door_ids[mem.editingfloor] > 0 then
local linecount = #mem.params.door_ids[mem.editingfloor]%10+1
for i=1,linecount,1 do
local line = ""
local start = (i-1)*10+1
for j=start,start+9,1 do
if j <= #mem.params.door_ids[mem.editingfloor] then
line = line..tostring(mem.params.door_ids[mem.editingfloor][j])..", "
end
end
if string.len(line) > 2 then
print(string.sub(line,1,-3))
end
end
else
print("NONE")
end
print()
print("* ADD DOOR")
print()
print("* REMOVE DOOR")
print()
print("]")
elseif mem.termstate == "adddoor" or mem.termstate == "removedoor" then
print()
print("DOOR ID?")
print("]")
elseif mem.termstate == "carcall" then
print()
print("FLOOR NUMBER?")
print("]")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment