![]() |
|
Again about semaphore - Printable Version +- LogicMachine Forum (https://forum.logicmachine.net) +-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1) +--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8) +--- Thread: Again about semaphore (/showthread.php?tid=3008) |
Again about semaphore - Andey - 23.11.2020 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
endFrom 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. RE: Again about semaphore - admin - 24.11.2020 Restarting the script during execution can break the semaphore status. My suggestion is to use only one resident script that combines RS485 and localbus for monitoring certain objects and writing to the port when values change. You can also use string.char instead of string.format so you don't have to worry about the format string having correct number of elements. RE: Again about semaphore - Andey - 24.11.2020 Hello I understand that single resident script is better practice. And semaphore is not necessary in this case. But there are some other events (not only timer to start resident script) that can to cause access to RS485 bus. These events can be object change by modbus profile mapping engine or object change from visualization. So I see potential parallel access to RS485. Now resident script is a test for semaphore usage. And I see that it logs output message continuously with proper timeout when semaphore is not used (commented) and only several logs when semaphore is used. I think some script debug tips (set breakpoint, steps running) can to help me to describe the problem in more details. But I do not know does debug is available at all for scripts. Can you to suggest me something to implement and report you more information? Thanks for tip with string.char method usage. |