diff --git a/coordinator/coordinator.lua b/coordinator/coordinator.lua
index 22e79d9..655ce58 100644
--- a/coordinator/coordinator.lua
+++ b/coordinator/coordinator.lua
@@ -18,6 +18,7 @@ local println_ts = util.println_ts
 local PROTOCOLS = comms.PROTOCOLS
 local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
 local SCADA_CRDN_TYPES = comms.SCADA_CRDN_TYPES
+local CRDN_COMMANDS = comms.CRDN_COMMANDS
 
 -- request the user to select a monitor
 ---@param names table available monitors
@@ -306,11 +307,11 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, sv_wa
     end
 
     -- send a unit command
-    ---@param unit integer unit ID
     ---@param cmd CRDN_COMMANDS command
+    ---@param unit integer unit ID
     ---@param option any? optional options (like burn rate)
-    function public.send_command(unit, cmd, option)
-        _send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.COMMAND_UNIT, { unit, cmd, option })
+    function public.send_command(cmd, unit, option)
+        _send_sv(PROTOCOLS.SCADA_CRDN, SCADA_CRDN_TYPES.COMMAND_UNIT, { cmd, unit, option })
     end
 
     -- parse a packet
@@ -425,6 +426,22 @@ function coordinator.comms(version, modem, sv_port, sv_listen, api_listen, sv_wa
                             log.error("received invalid unit statuses packet")
                         end
                     elseif packet.type == SCADA_CRDN_TYPES.COMMAND_UNIT then
+                        -- unit command acknowledgement
+                        if packet.length == 3 then
+                            local cmd = packet.data[1]
+                            local unit = packet.data[2]
+                            local ack = packet.data[3]
+                            
+                            if cmd == CRDN_COMMANDS.SCRAM then
+                            elseif cmd == CRDN_COMMANDS.START then
+                            elseif cmd == CRDN_COMMANDS.RESET_RPS then
+                            elseif cmd == CRDN_COMMANDS.SET_BURN then
+                            elseif cmd == CRDN_COMMANDS.SET_WASTE then
+                            else
+                            end
+                        else
+                            log.debug("unit command ack packet length mismatch")
+                        end
                     elseif packet.type == SCADA_CRDN_TYPES.ALARM then
                     else
                         log.warning("received unknown SCADA_CRDN packet type " .. packet.type)
diff --git a/coordinator/iocontrol.lua b/coordinator/iocontrol.lua
index bc93f05..339ad63 100644
--- a/coordinator/iocontrol.lua
+++ b/coordinator/iocontrol.lua
@@ -34,25 +34,10 @@ function iocontrol.init(conf, comms)
             burn_rate_cmd = 0.0,
             waste_control = 0,
 
-            start = function ()
-                comms.send_command(i, CRDN_COMMANDS.START)
-                log.debug(util.c("sent unit ", i, ": START"))
-            end,
-
-            scram = function ()
-                comms.send_command(i, CRDN_COMMANDS.SCRAM)
-                log.debug(util.c("sent unit ", i, ": SCRAM"))
-            end,
-
-            reset_rps = function ()
-                comms.send_command(i, CRDN_COMMANDS.RESET_RPS)
-                log.debug(util.c("sent unit ", i, ": RESET_RPS"))
-            end,
-
-            set_burn = function (rate)
-                comms.send_command(i, CRDN_COMMANDS.SET_BURN, rate)
-                log.debug(util.c("sent unit ", i, ": SET_BURN = ", rate))
-            end,
+            start = function () end,
+            scram = function () end,
+            reset_rps = function () end,
+            set_burn = function (rate) end,
 
             reactor_ps = psil.create(),
             reactor_data = {},  ---@type reactor_db
@@ -64,12 +49,36 @@ function iocontrol.init(conf, comms)
             turbine_data_tbl = {}
         }
 
+        function entry.start()
+            entry.control_state = true
+            comms.send_command(CRDN_COMMANDS.START, i)
+            log.debug(util.c("UNIT[", i, "]: START"))
+        end
+
+        function entry.scram()
+            entry.control_state = false
+            comms.send_command(CRDN_COMMANDS.SCRAM, i)
+            log.debug(util.c("UNIT[", i, "]: SCRAM"))
+        end
+
+        function entry.reset_rps()
+            comms.send_command(CRDN_COMMANDS.RESET_RPS, i)
+            log.debug(util.c("UNIT[", i, "]: RESET_RPS"))
+        end
+
+        function entry.set_burn(rate)
+            comms.send_command(CRDN_COMMANDS.SET_BURN, i, rate)
+            log.debug(util.c("UNIT[", i, "]: SET_BURN = ", rate))
+        end
+
+        -- create boiler tables
         for _ = 1, conf.defs[(i * 2) - 1] do
             local data = {} ---@type boilerv_session_db
             table.insert(entry.boiler_ps_tbl, psil.create())
             table.insert(entry.boiler_data_tbl, data)
         end
 
+        -- create turbine tables
         for _ = 1, conf.defs[i * 2] do
             local data = {} ---@type turbinev_session_db
             table.insert(entry.turbine_ps_tbl, psil.create())
diff --git a/coordinator/startup.lua b/coordinator/startup.lua
index aed8ac0..915cb26 100644
--- a/coordinator/startup.lua
+++ b/coordinator/startup.lua
@@ -16,7 +16,7 @@ local config       = require("coordinator.config")
 local coordinator  = require("coordinator.coordinator")
 local renderer     = require("coordinator.renderer")
 
-local COORDINATOR_VERSION = "alpha-v0.5.4"
+local COORDINATOR_VERSION = "alpha-v0.5.5"
 
 local print = util.print
 local println = util.println
diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua
index e3c80f7..3db1da7 100644
--- a/supervisor/session/coordinator.lua
+++ b/supervisor/session/coordinator.lua
@@ -182,26 +182,29 @@ function coordinator.new_session(id, in_queue, out_queue, facility_units)
             elseif pkt.type == SCADA_CRDN_TYPES.COMMAND_UNIT then
                 if pkt.length >= 2 then
                     -- get command and unit id
-                    local uid = pkt.data[1]
-                    local cmd = pkt.data[2]
+                    local cmd = pkt.data[1]
+                    local uid = pkt.data[2]
+
+                    -- pkt.data[3] will be nil except for some commands
+                    local data = { uid, pkt.data[3] }
 
                     -- continue if valid unit id
                     if util.is_int(uid) and uid > 0 and uid <= #self.units then
                         if cmd == CRDN_COMMANDS.START then
-                            self.out_q.push_data(SV_Q_DATA.START, uid)
+                            self.out_q.push_data(SV_Q_DATA.START, data)
                         elseif cmd == CRDN_COMMANDS.SCRAM then
-                            self.out_q.push_data(SV_Q_DATA.SCRAM, uid)
+                            self.out_q.push_data(SV_Q_DATA.SCRAM, data)
                         elseif cmd == CRDN_COMMANDS.RESET_RPS then
-                            self.out_q.push_data(SV_Q_DATA.RESET_RPS, uid)
+                            self.out_q.push_data(SV_Q_DATA.RESET_RPS, data)
                         elseif cmd == CRDN_COMMANDS.SET_BURN then
                             if pkt.length == 3 then
-                                self.out_q.push_data(SV_Q_DATA.SET_BURN, { uid, pkt.data[3] })
+                                self.out_q.push_data(SV_Q_DATA.SET_BURN, data)
                             else
                                 log.debug(log_header .. "CRDN command unit burn rate missing option")
                             end
                         elseif cmd == CRDN_COMMANDS.SET_WASTE then
                             if pkt.length == 3 then
-                                self.out_q.push_data(SV_Q_DATA.SET_WASTE, { uid, pkt.data[3] })
+                                self.out_q.push_data(SV_Q_DATA.SET_WASTE, data)
                             else
                                 log.debug(log_header .. "CRDN command unit set waste missing option")
                             end
diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua
index a233387..514cd60 100644
--- a/supervisor/session/plc.lua
+++ b/supervisor/session/plc.lua
@@ -11,6 +11,8 @@ local PROTOCOLS = comms.PROTOCOLS
 local RPLC_TYPES = comms.RPLC_TYPES
 local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES
 
+local CRDN_COMMANDS = comms.CRDN_COMMANDS
+
 local print = util.print
 local println = util.println
 local print_ts = util.print_ts
@@ -336,6 +338,13 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
                 elseif ack == false then
                     log.debug(log_header .. "burn rate update failed!")
                 end
+
+                -- send acknowledgement to coordinator
+                self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
+                    unit = self.for_reactor,
+                    cmd = CRDN_COMMANDS.SET_BURN,
+                    ack = ack
+                })
             elseif pkt.type == RPLC_TYPES.RPS_ENABLE then
                 -- enable acknowledgement
                 local ack = _get_ack(pkt)
@@ -345,6 +354,13 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
                 elseif ack == false then
                     log.debug(log_header .. "enable failed!")
                 end
+
+                -- send acknowledgement to coordinator
+                self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
+                    unit = self.for_reactor,
+                    cmd = CRDN_COMMANDS.START,
+                    ack = ack
+                })
             elseif pkt.type == RPLC_TYPES.RPS_SCRAM then
                 -- SCRAM acknowledgement
                 local ack = _get_ack(pkt)
@@ -354,6 +370,13 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
                 elseif ack == false then
                     log.debug(log_header .. "SCRAM failed!")
                 end
+
+                -- send acknowledgement to coordinator
+                self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
+                    unit = self.for_reactor,
+                    cmd = CRDN_COMMANDS.SCRAM,
+                    ack = ack
+                })
             elseif pkt.type == RPLC_TYPES.RPS_STATUS then
                 -- RPS status packet received, copy data
                 if pkt.length == 9 then
@@ -392,6 +415,13 @@ function plc.new_session(id, for_reactor, in_queue, out_queue)
                 elseif ack == false then
                     log.debug(log_header .. "RPS reset failed")
                 end
+
+                -- send acknowledgement to coordinator
+                self.out_q.push_data(svqtypes.SV_Q_DATA.CRDN_ACK, {
+                    unit = self.for_reactor,
+                    cmd = CRDN_COMMANDS.RESET_RPS,
+                    ack = ack
+                })
             else
                 log.debug(log_header .. "handler received unsupported RPLC packet type " .. pkt.type)
             end
diff --git a/supervisor/session/svqtypes.lua b/supervisor/session/svqtypes.lua
index 175f98b..19f9d54 100644
--- a/supervisor/session/svqtypes.lua
+++ b/supervisor/session/svqtypes.lua
@@ -9,7 +9,9 @@ local SV_Q_DATA = {
     SCRAM = 2,
     RESET_RPS = 3,
     SET_BURN = 4,
-    SET_WASTE = 5
+    SET_WASTE = 5,
+    __END_PLC_CMDS__ = 6,
+    CRDN_ACK = 7
 }
 
 svqtypes.SV_Q_CMDS = SV_Q_CMDS
diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua
index 2c42f91..d2ccad0 100644
--- a/supervisor/session/svsessions.lua
+++ b/supervisor/session/svsessions.lua
@@ -70,25 +70,30 @@ local function _sv_handle_outq(session)
             elseif msg.qtype == mqueue.TYPE.DATA then
                 -- instruction/notification with body
                 local cmd = msg.message ---@type queue_data
-                local plc_s = nil
 
-                if type(cmd.val) == "table" then
-                    plc_s = svsessions.get_reactor_session(cmd.val[1])
-                elseif type(cmd.val) == "number" then
-                    plc_s = svsessions.get_reactor_session(cmd.val)
-                end
+                if cmd.key < SV_Q_DATA.__END_PLC_CMDS__ then
+                    -- PLC commands from coordinator
+                    local crdn_sid = session.instance.get_id()
+                    local plc_s = svsessions.get_reactor_session(cmd.val[1])
 
-                if plc_s ~= nil then
-                    if cmd.key == SV_Q_DATA.START then
-                        plc_s.in_queue.push_command(PLC_S_CMDS.ENABLE)
-                    elseif cmd.key == SV_Q_DATA.SCRAM then
-                        plc_s.in_queue.push_command(PLC_S_CMDS.SCRAM)
-                    elseif cmd.key == SV_Q_DATA.RESET_RPS then
-                        plc_s.in_queue.push_command(PLC_S_CMDS.RPS_RESET)
-                    elseif cmd.key == SV_Q_DATA.SET_BURN and type(cmd.val) == "table" and #cmd.val == 2 then
-                        plc_s.in_queue.push_data(PLC_S_DATA.BURN_RATE, cmd.val[2])
-                    elseif cmd.key == SV_Q_DATA.SET_WASTE and type(cmd.val) == "table" and #cmd.val == 2 then
-                        ---@todo set waste
+                    if plc_s ~= nil then
+                        if cmd.key == SV_Q_DATA.START then
+                            plc_s.in_queue.push_command(PLC_S_CMDS.ENABLE)
+                        elseif cmd.key == SV_Q_DATA.SCRAM then
+                            plc_s.in_queue.push_command(PLC_S_CMDS.SCRAM)
+                        elseif cmd.key == SV_Q_DATA.RESET_RPS then
+                            plc_s.in_queue.push_command(PLC_S_CMDS.RPS_RESET)
+                        elseif cmd.key == SV_Q_DATA.SET_BURN and type(cmd.val) == "table" and #cmd.val == 2 then
+                            plc_s.in_queue.push_data(PLC_S_DATA.BURN_RATE, cmd.val[2])
+                        elseif cmd.key == SV_Q_DATA.SET_WASTE and type(cmd.val) == "table" and #cmd.val == 2 then
+                            ---@todo set waste
+                        else
+                            log.debug(util.c("unknown PLC SV queue command ", cmd.key))
+                        end
+                    end
+                else
+                    if cmd.key == SV_Q_DATA.CRDN_ACK then
+                        ---@todo ack to be sent to coordinator
                     end
                 end
             end
@@ -279,7 +284,7 @@ function svsessions.establish_plc_session(local_port, remote_port, for_reactor,
             r_port = remote_port,
             in_queue = mqueue.new(),
             out_queue = mqueue.new(),
-            instance = nil
+            instance = nil  ---@type plc_session
         }
 
         plc_s.instance = plc.new_session(self.next_plc_id, for_reactor, plc_s.in_queue, plc_s.out_queue)
@@ -317,7 +322,7 @@ function svsessions.establish_rtu_session(local_port, remote_port, advertisement
         r_port = remote_port,
         in_queue = mqueue.new(),
         out_queue = mqueue.new(),
-        instance = nil
+        instance = nil  ---@type rtu_session
     }
 
     rtu_s.instance = rtu.new_session(self.next_rtu_id, rtu_s.in_queue, rtu_s.out_queue, advertisement, self.facility_units)
@@ -346,7 +351,7 @@ function svsessions.establish_coord_session(local_port, remote_port, version)
         r_port = remote_port,
         in_queue = mqueue.new(),
         out_queue = mqueue.new(),
-        instance = nil
+        instance = nil  ---@type coord_session
     }
 
     coord_s.instance = coordinator.new_session(self.next_coord_id, coord_s.in_queue, coord_s.out_queue, self.facility_units)
diff --git a/supervisor/startup.lua b/supervisor/startup.lua
index 7d1fae1..b7acdfb 100644
--- a/supervisor/startup.lua
+++ b/supervisor/startup.lua
@@ -13,7 +13,7 @@ local svsessions = require("supervisor.session.svsessions")
 local config     = require("supervisor.config")
 local supervisor = require("supervisor.supervisor")
 
-local SUPERVISOR_VERSION = "beta-v0.6.3"
+local SUPERVISOR_VERSION = "beta-v0.6.4"
 
 local print = util.print
 local println = util.println