mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
181 lines
5.0 KiB
Lua
181 lines
5.0 KiB
Lua
PROTOCOLS = {
|
|
MODBUS_TCP = 0, -- our "MODBUS TCP"-esque protocol
|
|
RPLC = 1, -- reactor PLC protocol
|
|
SCADA_MGMT = 2, -- SCADA supervisor intercommunication, device advertisements, etc
|
|
COORD_DATA = 3 -- data packets for coordinators to/from supervisory controller
|
|
}
|
|
|
|
SCADA_SV_MODES = {
|
|
ACTIVE = 0, -- supervisor running as primary
|
|
BACKUP = 1 -- supervisor running as hot backup
|
|
}
|
|
|
|
RPLC_TYPES = {
|
|
KEEP_ALIVE = 0, -- keep alive packets
|
|
LINK_REQ = 1, -- linking requests
|
|
STATUS = 2, -- reactor/system status
|
|
MEK_STRUCT = 3, -- mekanism build structure
|
|
MEK_SCRAM = 4, -- SCRAM reactor
|
|
MEK_ENABLE = 5, -- enable reactor
|
|
MEK_BURN_RATE = 6, -- set burn rate
|
|
ISS_ALARM = 7, -- ISS alarm broadcast
|
|
ISS_GET = 8, -- get ISS status
|
|
ISS_CLEAR = 9 -- clear ISS trip (if in bad state, will trip immediately)
|
|
}
|
|
|
|
RPLC_LINKING = {
|
|
ALLOW = 0, -- link approved
|
|
DENY = 1, -- link denied
|
|
COLLISION = 2 -- link denied due to existing active link
|
|
}
|
|
|
|
SCADA_MGMT_TYPES = {
|
|
PING = 0, -- generic ping
|
|
SV_HEARTBEAT = 1, -- supervisor heartbeat
|
|
REMOTE_LINKED = 2, -- remote device linked
|
|
RTU_ADVERT = 3, -- RTU capability advertisement
|
|
RTU_HEARTBEAT = 4, -- RTU heartbeat
|
|
}
|
|
|
|
RTU_ADVERT_TYPES = {
|
|
BOILER = 0, -- boiler
|
|
TURBINE = 1, -- turbine
|
|
IMATRIX = 2, -- induction matrix
|
|
REDSTONE = 3 -- redstone I/O
|
|
}
|
|
|
|
-- generic SCADA packet object
|
|
function scada_packet()
|
|
local self = {
|
|
modem_msg_in = nil,
|
|
valid = false,
|
|
seq_num = nil,
|
|
protocol = nil,
|
|
length = nil,
|
|
raw = nil
|
|
}
|
|
|
|
local make = function (seq_num, protocol, payload)
|
|
self.valid = true
|
|
self.seq_num = seq_num
|
|
self.protocol = protocol
|
|
self.length = #payload
|
|
self.raw = { self.seq_num, self.protocol, self.length, payload }
|
|
end
|
|
|
|
local receive = function (side, sender, reply_to, message, distance)
|
|
self.modem_msg_in = {
|
|
iface = side,
|
|
s_port = sender,
|
|
r_port = reply_to,
|
|
msg = message,
|
|
dist = distance
|
|
}
|
|
|
|
self.raw = self.modem_msg_in.msg
|
|
|
|
if #self.raw < 3 then
|
|
-- malformed
|
|
return false
|
|
else
|
|
self.valid = true
|
|
self.seq_num = self.raw[1]
|
|
self.protocol = self.raw[2]
|
|
self.length = self.raw[3]
|
|
end
|
|
end
|
|
|
|
local modem_event = function () return self.modem_msg_in end
|
|
local raw = function () return self.raw end
|
|
|
|
local is_valid = function () return self.valid end
|
|
|
|
local seq_num = function () return self.seq_num end
|
|
local protocol = function () return self.protocol end
|
|
local length = function () return self.length end
|
|
|
|
local data = function ()
|
|
local subset = nil
|
|
if self.valid then
|
|
subset = { table.unpack(self.raw, 4, 3 + self.length) }
|
|
end
|
|
return subset
|
|
end
|
|
|
|
return {
|
|
make = make,
|
|
receive = receive,
|
|
modem_event = modem_event,
|
|
raw = raw,
|
|
is_valid = is_valid,
|
|
seq_num = seq_num,
|
|
protocol = protocol,
|
|
length = length,
|
|
data = data
|
|
}
|
|
end
|
|
|
|
function mgmt_packet()
|
|
local self = {
|
|
frame = nil,
|
|
type = nil,
|
|
length = nil,
|
|
data = nil
|
|
}
|
|
|
|
local _scada_type_valid = function ()
|
|
return self.type == SCADA_MGMT_TYPES.PING or
|
|
self.type == SCADA_MGMT_TYPES.SV_HEARTBEAT or
|
|
self.type == SCADA_MGMT_TYPES.REMOTE_LINKED or
|
|
self.type == SCADA_MGMT_TYPES.RTU_ADVERT or
|
|
self.type == SCADA_MGMT_TYPES.RTU_HEARTBEAT
|
|
end
|
|
|
|
-- make a SCADA management packet
|
|
local make = function (packet_type, length, data)
|
|
self.type = packet_type
|
|
self.length = length
|
|
self.data = data
|
|
end
|
|
|
|
-- decode a SCADA management packet from a SCADA frame
|
|
local decode = function (frame)
|
|
if frame then
|
|
self.frame = frame
|
|
|
|
if frame.protocol() == comms.PROTOCOLS.SCADA_MGMT then
|
|
local data = frame.data()
|
|
local ok = #data > 1
|
|
|
|
if ok then
|
|
make(data[1], data[2], { table.unpack(data, 3, #data) })
|
|
ok = _scada_type_valid()
|
|
end
|
|
|
|
return ok
|
|
else
|
|
log._debug("attempted SCADA_MGMT parse of incorrect protocol " .. frame.protocol(), true)
|
|
return false
|
|
end
|
|
else
|
|
log._debug("nil frame encountered", true)
|
|
return false
|
|
end
|
|
end
|
|
|
|
local get = function ()
|
|
return {
|
|
scada_frame = self.frame,
|
|
type = self.type,
|
|
length = self.length,
|
|
data = self.data
|
|
}
|
|
end
|
|
|
|
return {
|
|
make = make,
|
|
decode = decode,
|
|
get = get
|
|
}
|
|
end
|