require("rsmdict")

--The Objects that is supported by the Script
local obj_ids = {
                   RSM.RSM_TagID.TAG_BUS_SERIAL                    
                }
                
local devices = {}
local serial_file = ""
local serial_conf_file="/etc/rsm/serialconf.xml"
local serial_conf_file_test="/usr/share/lua/kses/test_bus_serial.xml"

local modbusFiles = {}
local flddFiles = {}
local modbusPath = "/etc/rsm/mdd/devices/"
local flddPath = "/etc/rsm/fldd/devices/"


local sdd_down = "/usr/bin/sv down sdd"
local sdd_up = "/usr/bin/sv up sdd"

local rdd_down = "/usr/bin/sv down rdd"
local rdd_up = "/usr/bin/sv up rdd"

local mdd_down = "/usr/bin/sv down mdd"
local mdd_up = "/usr/bin/sv up mdd"

local ddd_down = "/usr/bin/sv down ddd"
local ddd_up = "/usr/bin/sv up ddd"

local fldd_down = "/usr/bin/sv down fldd"
local fldd_up = "/usr/bin/sv up fldd"

local tsd_down = "/usr/bin/sv down tsd"
local tsd_up = "/usr/bin/sv up tsd"

function print_table(t,p)

   for k,v in pairs(t) do
     print(p,k,v)
     if(type(v)=="table") then 
         print_table(v,p.."\t")
     end
  end
end


--Retuen the Object List
function getObjects()
 return obj_ids;
end

--Convert the config file into an object message nd return that.
--Actually supposed to check the request object to find the exact object if any to 
--return. We jippo that by always returning all of them
function getConfig(cfg)
  load_serial()
  msg = serial_to_msg()
  return msg
end


--Function to lookup and set a specific object(s)
--and then to update the cofig file with those values
function setConfig(cfg)
   load_serial()   
   update_serial(cfg)
   store_serial()
end


function command_exec(cmd)
  local f = io.popen(cmd) 
  value = f:read("*a") or "none"
  f:close()
  return value
end

function scandir(directory)
  local i, t, popen = 0, {}, io.popen
    for filename in popen('ls -a "'..directory..'"'):lines() do
        i = i + 1
        t[i] = filename
    end
    return t
end

function writefile(fileaddres,value)
  local f = io.open(fileaddres,"w+")
  f:write(value)
  f:close()
  return true
end

function load_serial() 
  --print("Loading pf data...")   
  sf = command_exec("cat "..serial_conf_file)  
  serial_file = sf  
  devices = {}  
  
  if(modbusPath ~= "") then
    modbusFiles = scandir(modbusPath)
  end
  if(flddPath ~= "") then
    flddFiles = scandir(flddPath)
  end
  
    
  --Add pf services Objects
  if(sf ~= "") then
  
    for device, sfConf in (serial_file:gmatch('<port%s+device=%"(.-)%"%s->(.-)</port>')) do
    --deviceCount = deviceCount + 1
    devices[device] = {}
    devices[device].device = device or "unknown"
    devices[device].owner = sfConf:match("<owner>%s-(.-)%s-</owner>") or "" -- type is "owner" in xml   
    devices[device].baud = sfConf:match("<baud>%s-(%d+)%s-</baud>") or "115200"
    devices[device].data = sfConf:match("<data>%s-(%d+)%s-</data>") or "8"
    devices[device].stop = sfConf:match("<stop>%s-(%d+)%s-</stop>") or "1"
    devices[device].mode = sfConf:match("<mode>%s-(.-)%s-</mode>") or "rs485"
    devices[device].nonblock = sfConf:match("<nonblock>%s-(.-)%s-</nonblock>") or "true"
    devices[device].deviceCount = 0
    
    for i,f in pairs(modbusFiles) do
      temp = command_exec("cat "..modbusPath.."/"..f)
      if temp:match("<port>%s-(.-)%s-</port>") == device then
        devices[device].deviceCount  = devices[device].deviceCount  + 1
      end--if
    end--for
    for i,f in pairs(flddFiles) do
      temp = command_exec("cat "..flddPath.."/"..f)
      if temp:match("<port>%s-(.-)%s-</port>") == device then
        devices[device].deviceCount  = devices[device].deviceCount  + 1
      end--if
    end--for
    
    end
  end -- if sf
   
              
end

function serial_to_msg()
  local msg = {}
  serial_ctr = 0
  
  --print("Load Message: ")
  --Send Subnet info
  for idx,sff in pairs(devices) do
     serial_cfg = {}
     serial_cfg.objid =  RSM.RSM_TagID.TAG_BUS_SERIAL
     serial_cfg[RSM.RSM_TagID.TAG_BUS_DEVICE] = sff.device
     
     if (sff.owner == "rdd") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_OWNER] = RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_RDD
     elseif (sff.owner == "mdd") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_OWNER] = RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_MDD 
     elseif (sff.owner == "ddd") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_OWNER] = RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_DDD  
     elseif (sff.owner == "fldd") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_OWNER] = RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_FLDD 
     elseif (sff.owner == "tsd") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_OWNER] = RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_TSD 
     end 
     
     if (sff.nonblock == "true") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_NBLOCK] = RSM.TAG_BUS_NBLOCK_Types.TAG_BUS_NBLOCK_TRUE
     elseif (sff.nonblock == "false") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_NBLOCK] = RSM.TAG_BUS_NBLOCK_Types.TAG_BUS_NBLOCK_FALSE     
     end   
     
     if (sff.mode == "rs232") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_MODE] = RSM.TAG_BUS_MODE_Types.TAG_BUS_MODE_RS232
     elseif (sff.mode == "rs485") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_MODE] = RSM.TAG_BUS_MODE_Types.TAG_BUS_MODE_RS485     
     end             
     
     if (sff.stop == "1") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_STOP] = RSM.TAG_BUS_STOP_Types.TAG_BUS_STOP_ONE
     elseif (sff.stop == "1.5") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_STOP] = RSM.TAG_BUS_STOP_Types.TAG_BUS_STOP_ONEFIVE
     elseif (sff.stop == "2") then
        serial_cfg[RSM.RSM_TagID.TAG_BUS_STOP] = RSM.TAG_BUS_STOP_Types.TAG_BUS_STOP_TWO 
     end
     
     serial_cfg[RSM.RSM_TagID.TAG_BUS_BAUD] = tonumber(sff.baud)
     serial_cfg[RSM.RSM_TagID.TAG_BUS_DATA] = tonumber(sff.data)    
     
          
     msg[serial_ctr] = serial_cfg
     serial_ctr = serial_ctr+1
  end  
  
  return msg
end

function update_serial(cfg)
   for idx,obj in pairs(cfg) do      
      if obj.objid and obj.objid == RSM.RSM_TagID.TAG_BUS_SERIAL then
          if obj[RSM.RSM_TagID.TAG_BUS_DEVICE] then         
              --devices[obj[RSM.RSM_TagID.TAG_BUS_DEVICE]]={}     
              sf = devices[obj[RSM.RSM_TagID.TAG_BUS_DEVICE]]              
              --print("Adding object: " .. obj[RSM.RSM_TagID.TAG_NET_LABEL]);
              if sf then
                setdevices(sf,obj)
              end
          end 
      end      
   end 
end


function setdevices(sf,obj)

    if obj[RSM.RSM_TagID.TAG_BUS_OWNER] then    
       if obj[RSM.RSM_TagID.TAG_BUS_OWNER] == RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_RDD then  
          sf.owner = "rdd"
       end 
       if obj[RSM.RSM_TagID.TAG_BUS_OWNER] == RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_MDD then  
          sf.owner = "mdd"
       end 
       if obj[RSM.RSM_TagID.TAG_BUS_OWNER] == RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_DDD then  
          sf.owner = "ddd"
       end 
       if obj[RSM.RSM_TagID.TAG_BUS_OWNER] == RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_FLDD then  
          sf.owner = "fldd"
       end 
       if obj[RSM.RSM_TagID.TAG_BUS_OWNER] == RSM.TAG_BUS_OWNER_Types.TAG_BUS_OWNER_TSD then  
          sf.owner = "tsd"
       end
    end
    
    if obj[RSM.RSM_TagID.TAG_BUS_NBLOCK] then    
       if obj[RSM.RSM_TagID.TAG_BUS_NBLOCK] == RSM.TAG_BUS_NBLOCK_Types.TAG_BUS_NBLOCK_TRUE then  
          sf.nonblock = "true"
       end 
       if obj[RSM.RSM_TagID.TAG_BUS_NBLOCK] == RSM.TAG_BUS_NBLOCK_Types.TAG_BUS_NBLOCK_FALSE then  
          sf.nonblock = "false"
       end   
    end
    
    if obj[RSM.RSM_TagID.TAG_BUS_MODE] then    
       if obj[RSM.RSM_TagID.TAG_BUS_MODE] == RSM.TAG_BUS_MODE_Types.TAG_BUS_MODE_RS232 then  
          sf.mode = "rs232"
       end 
       if obj[RSM.RSM_TagID.TAG_BUS_MODE] == RSM.TAG_BUS_MODE_Types.TAG_BUS_MODE_RS485 then  
          sf.mode = "rs485"
       end   
    end
    
    if obj[RSM.RSM_TagID.TAG_BUS_STOP] then    
       if obj[RSM.RSM_TagID.TAG_BUS_STOP] == RSM.TAG_BUS_STOP_Types.TAG_BUS_STOP_ONE then  
          sf.stop = "1"
       end 
       if obj[RSM.RSM_TagID.TAG_BUS_STOP] == RSM.TAG_BUS_STOP_Types.TAG_BUS_STOP_ONEFIVE then  
          sf.stop = "1.5"
       end 
       if obj[RSM.RSM_TagID.TAG_BUS_STOP] == RSM.TAG_BUS_STOP_Types.TAG_BUS_STOP_TWO then  
          sf.stop = "2"
       end        
    end
    
    
    if obj[RSM.RSM_TagID.TAG_BUS_BAUD] then
    
        if obj[RSM.RSM_TagID.TAG_BUS_BAUD] == 49664 then
          sf.baud = 115200
        else
          sf.baud = obj[RSM.RSM_TagID.TAG_BUS_BAUD]
        end
    end
    if obj[RSM.RSM_TagID.TAG_BUS_DATA] then
       sf.data = obj[RSM.RSM_TagID.TAG_BUS_DATA]
    end
    
     
    sf.changed = 1
    print("Device-Changed status: " ..sf.changed)
end

function store_serial()

  for idx,sf in pairs(devices) do
         if sf.changed and sf.changed == 1 then
            --local serial_config = "<!-- "..serial_conf_file.." generated by webconfig -->\n"
            --serial_config = serial_config.."<config>\n"
            --serial_config = serial_config.."\t<serialconfig>\n"
            local serial_config = '<port device="' ..sf.device .. '">\n'
            serial_config = serial_config..'            <owner>' ..sf.owner .. '</owner>\n'
            serial_config = serial_config..'            <baud>' ..sf.baud .. '</baud>\n'
            serial_config = serial_config..'            <data>' ..sf.data .. '</data>\n'
            serial_config = serial_config..'            <stop>' ..sf.stop .. '</stop>\n'
            serial_config = serial_config..'            <nonblock>' ..sf.nonblock .. '</nonblock>\n'
            serial_config = serial_config..'            <mode>' ..sf.mode .. '</mode>\n'
            serial_config = serial_config..'      </port>\n'             

            print("***Printing new device contents: \n"..serial_config)   
            
            serial_file = serial_file:gsub('<port device="' ..sf.device .. '">.-</port>\n', serial_config)
         end       
  end   
  
  command_exec(rdd_down)
  command_exec(mdd_down)
  command_exec(ddd_down)
  command_exec(fldd_down)
  command_exec(tsd_down)
  command_exec(sdd_down)
  
  writefile(serial_conf_file,serial_file)
  
  command_exec(rdd_up)
  command_exec(mdd_up)
  command_exec(ddd_up)
  command_exec(fldd_up)
  command_exec(tsd_up)
  command_exec(sdd_up)
end

--Testing....

--[[print("Testing...")
--print("Get Config: ")

print_table(getConfig(),0)

local testCfg = {}
local obj ={}
local obj1 ={}

obj.objid = RSM.RSM_TagID.TAG_BUS_SERIAL
obj[RSM.RSM_TagID.TAG_BUS_DEVICE] = "/dev/ttyS1"     
--obj[RSM.RSM_TagID.TAG_BUS_OWNER] = "mdd"
--obj[RSM.RSM_TagID.TAG_BUS_BAUD] = 9600
--obj[RSM.RSM_TagID.TAG_BUS_DATA] = 5
--obj[RSM.RSM_TagID.TAG_BUS_STOP] = 1
obj[RSM.RSM_TagID.TAG_BUS_NBLOCK] = 1
--obj[RSM.RSM_TagID.TAG_BUS_MODE] = 1

obj1.objid = RSM.RSM_TagID.TAG_BUS_SERIAL
obj1[RSM.RSM_TagID.TAG_BUS_DEVICE] = "/dev/ttyS3"     
--obj1[RSM.RSM_TagID.TAG_BUS_OWNER] = "rdd"
obj1[RSM.RSM_TagID.TAG_BUS_BAUD] = 9600
obj1[RSM.RSM_TagID.TAG_BUS_DATA] = 8
--obj1[RSM.RSM_TagID.TAG_BUS_STOP] = 1
--obj1[RSM.RSM_TagID.TAG_BUS_NBLOCK] = 0
--obj1[RSM.RSM_TagID.TAG_BUS_MODE] = 0

testCfg[0] = obj
testCfg[1] = obj1

setConfig(testCfg)]]--





























