This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Again about semaphore
#1
Hello.
In my home I have FN485 devices. They are controlled via dedicated RS485 bus. FN485 can to operate as stand alone device - it has input and output, when input is closed output relay is closed too. But I decided that I need additional control. To turn light from application, to know what inputs are closed, to turn light when switch that is controlled by other device is toggled. So I see at least three events that can to access to RS485 bus to operate with FN485. And I decided that I need to manage access to serial bus. The only way I know is to use semaphore. In scripting tab/user library  I have created script you can to see below
Code:
require('sem')
require('serial')

function readSerialFN485()
  local buf = {}
  while true do
    local timeout = #buf > 0 and 0.5 or 15
    local char = port:read(1, timeout)
   
    if char then
      buf[ #buf + 1 ] = char:byte()
    else
      return buf
    end
  end
end


function FN485_write(param1, relay, value)

  local semaphore = sem.open("FN485_serial_access")
  if semaphore:trywait() == false then
    semaphore:wait()
  end
 
  if not port then
    port = serial.open('/dev/RS485-1', { baudrate = 9600, duplex = 'half' })
    port:flush()
  end
 
  data_addr = 100 + param1
  data_relay = 100 + relay
  data_value = 100
  if value then
    data_value = 100 + 1
  end
 
  qqq = string.format('%c%c%c%c%c%c%c%c%c%c', 99, data_addr, data_addr, 211, 211, data_relay, data_relay, data_value, data_value, 13)
  if port then
    port:write(qqq)
    port:drain()
  end
 
  semaphore:post()
 
end
-- function reads all input states
-- returns bitwise UINT8 value; bit 0 = state of input 0
function FN485_read_all_inputs(param1)
  local semaphore = sem.open("FN485_serial_access")
  if semaphore:trywait() == false then
    semaphore:wait()
  end
 
  if not port then
    port = serial.open('/dev/RS485-1', { baudrate = 9600, duplex = 'half' })
    port:flush()
  end
 
  data_addr = 100 + param1
 
  qqq = string.format('%c%c%c%c%c%c%c%c%c%c', 99, data_addr, data_addr, 109, 109, 100, 100, 100, 100, 13)
  if port then
    port:write(qqq)
    port:drain()
   
    res = readSerialFN485()
   
  end
 
 
  -- parse read result
  if res then
    -- check read parameters and if parameters are OK return something
    if (res[2] == data_addr and res[3] == data_addr and res[4] == 109 and res[5] == 109) then
      local retValue = bit.lshift( res[7] - 100, 4) + res[9] - 100
      return retValue
    else
      log(res)
    end
  end
end

From point of view code is correct. 
For test purposes I have started to call read all input function from resident script with log output each time after read_all_inputs function is called. And I see that log is properly created only several times. Then I need to open resident script and save it to get again only several logs. But had expected continuous logs with timeout I had specified for resident script.
 What I am doing wrong.
Reply


Messages In This Thread
Again about semaphore - by Andey - 23.11.2020, 19:53
RE: Again about semaphore - by admin - 24.11.2020, 07:46
RE: Again about semaphore - by Andey - 24.11.2020, 09:21

Forum Jump: