Author Topic: Automatically adjust the read value returned via serial connection ?  (Read 732 times)

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Hi

Not sure if this is possible or not, but Im working on some basic code to test/control another hdmi matrix - below..

Code: [Select]
function HDMIA1()
local socket = require("socket")
host = "192.168.1.147"
c = assert(socket.connect(host, 4002))
c:settimeout(5)
local sres, serr = c:send(string.char(0x02,0x32,0x31,0x31,0x03))
print("Send:", sres, serr)
local data, rerr = c:receive(300)
luup.log (data)
print ("Receive:", data, rerr)
c:close()

end

HDMIA1()

I have noticed that depending on the HEX command that is sent it can time out if the c:receive(xxx) value is too large. While a low value works for all of them. For some everything that the matrix returns it needs to be 300 long , for the more quick commands I can set it to e.g 100 for it to work.

To deal with this, does anyone know how to code that part of the above so that it can automatically adjust in size or does each command need to have its own c:receive(xxx) associated ?

(The timeout value does not seem to play a part, it seems to relate to the number of characters it returns)

Here are a couple of examples of HEX commands that can be sent and the maximum c:receive value I can assign, any higher for each one and it will not complete and time out.

Code: [Select]
local sres, serr = c:send(string.char(0x73,0x77,0x20,0x69,0x30,0x31,0x20,0x6f,0x30,0x33,0x0d,0x0a))
print("Send:", sres, serr)
local data, rerr = c:receive(113)


Code: [Select]
local sres, serr = c:send(string.char(0x72,0x65,0x61,0x64,0x0d,0x0a))
print("Send:", sres, serr)
local data, rerr = c:receive(314)
« Last Edit: June 10, 2018, 02:57:51 pm by parkerc »

Offline akbooer

  • Master Member
  • *******
  • Posts: 6153
  • Karma: +275/-69
  • "Less is more"
Re: Automatically adjust the read value returned via serial connection ?
« Reply #1 on: June 10, 2018, 03:20:43 pm »
The serial protocol should define a termination character.  A fixed length read is simply not appropriate for variable length messages!  Vera supports a number of message protocols/terminators, including <cr>, <cr><lf>, <stx><etx>.  What documentation do you have for your device?
« Last Edit: June 10, 2018, 06:27:58 pm by akbooer »
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Automatically adjust the read value returned via serial connection ?
« Reply #2 on: June 10, 2018, 03:38:14 pm »
Hi @akbooer

The serial commands are here.

http://assets.aten.com/product/manual/vm0404h-s_2014-03-20.pdf

Its an ATEN Matrix, I?m currently converting their ASCII commands to HEX.

https://eservice.aten.com/eServiceCx/Common/FAQ/view.do?id=3975





Offline akbooer

  • Master Member
  • *******
  • Posts: 6153
  • Karma: +275/-69
  • "Less is more"
Re: Automatically adjust the read value returned via serial connection ?
« Reply #3 on: June 10, 2018, 04:17:14 pm »
Well, it's clear that both send and receiving use the CRLF terminator, and this is one supported by Vera.  If you use the luup.io package, then the end of line handling is taken care for you, if you have set the correct protocol.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline akbooer

  • Master Member
  • *******
  • Posts: 6153
  • Karma: +275/-69
  • "Less is more"
Re: Automatically adjust the read value returned via serial connection ?
« Reply #4 on: June 10, 2018, 04:21:22 pm »
Actually, on further thought, you can achieve the same with the socket package that you've set out using.

Look at the read patterns defined here: http://w3.impa.br/~diego/software/luasocket/tcp.html#receive
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Automatically adjust the read value returned via serial connection ?
« Reply #5 on: June 10, 2018, 05:23:31 pm »
Thanks

Trying the options I get the following returned, it seems only the ?number? options can show all what the matrix can return.

Code: [Select]
local data, rerr = c:receive(225)
Quote
Print output
Send:     6     
Receive:     ??? ??? ??read Command OK
o01 i02 video on audio on CEC off
o02 i01 video on audio on CEC off
o03 i01 video on audio on CEC off
o04 i01 video on audio on CEC off
FW: V2.2.213
FPGA: V1.0.076
EDID: default     

Code: [Select]
local data, rerr = c:receive('*l')
Quote
Print output
Send:     6     
Receive:     ??? ??? ??read Command OK     


Code: [Select]
local data, rerr = c:receive('*a')
Quote
Send:     6     
Receive:     nil     timeout
« Last Edit: June 10, 2018, 05:29:17 pm by parkerc »

Offline akbooer

  • Master Member
  • *******
  • Posts: 6153
  • Karma: +275/-69
  • "Less is more"
Re: Automatically adjust the read value returned via serial connection ?
« Reply #6 on: June 10, 2018, 06:39:43 pm »
Yes, that's because the sender keeps the socket open, after a transmission.  You might try reading line-by-line to get the data you need.  It may also be worthwhile setting the tcp-nodelay option described here, if you plan on interleaving receive and send requests alternately to the same socket.

http://w3.impa.br/~diego/software/luasocket/tcp.html#setoption
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Automatically adjust the read value returned via serial connection ?
« Reply #7 on: June 11, 2018, 02:33:08 pm »
Hi @akbooer

Many thanks for your suggestions, I tried the option as you suggested, changing c:receive to c:setoption

Code: [Select]
local data, rerr = c:setoption('tcp-nodelay', true)
but that just returns the following (luatest extract)

Quote
Results
No errors
Runtime: 3.4 ms
Code returned: nil

Print output
Send:     6     
Receive:     1     

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Automatically adjust the read value returned via serial connection ?
« Reply #8 on: June 11, 2018, 02:49:51 pm »
I had a go at switching things over to Luup.io.xxxx, but I?m not having much luck with that route.

Quote
LuaTest 1.7

Lua file: /nas/luatest/luup-io.lua

Results
No errors
Runtime: 2.2 ms
Code returned: nil

Print output


Code
   1   
   2   
   3   local incoming_data = ""
   4   
   5    luup.io.intercept()
   6    luup.io.write(string.char(0x72,0x65,0x61,0x64,0x0d,0x0a), "192.168.1.147", 4002)
   7    incoming_data = luup.io.read()
   8    luup.log(incoming_data)
   9   
  10    print(incoming_data)

Offline akbooer

  • Master Member
  • *******
  • Posts: 6153
  • Karma: +275/-69
  • "Less is more"
Re: Automatically adjust the read value returned via serial connection ?
« Reply #9 on: June 11, 2018, 03:02:50 pm »
Quote
I tried the option as you suggested, changing c:receive to c:setoption

That's not what I suggested!  I was asking just to add the line to set that option and then continue using receive, line by line.

On your later experiment, yes, luup.io is tricky too.  It's designed for use in plugins, so I,m not sure how it would fare in LuaTest.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Automatically adjust the read value returned via serial connection ?
« Reply #10 on: June 11, 2018, 03:20:52 pm »
Ok, I tired it with c:receive first ,  but as it just timed out I assumed it must be a replacement - let me try again.

Also please hold off on the ?!? - If I misinterpreted anything I?m sorry.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Automatically adjust the read value returned via serial connection ?
« Reply #11 on: June 11, 2018, 03:35:34 pm »
Sadly still the same results as before, I only seem to be able to get the most information back by defining the number of bytes. E.g. (255)

Here is my current code, with the c:receive options.

Code: [Select]
function HDMIA1()
   local socket = require("socket")
   host = "192.168.1.147"
   c = assert(socket.connect(host, 4002))
   c:settimeout(5)
   c:setoption('tcp-nodelay', true)

-- read matrix status
   local sres, serr = c:send(string.char(0x72,0x65,0x61,0x64,0x0d,0x0a))
   
-- reset matrix
-- local sres, serr = c:send(string.char(0x72,0x65,0x73,0x65,0x74,0x0d,0x0a))

   print("Send:", sres, serr)
   local data, rerr = c:receive('*a')
   -- local data, rerr = c:receive('*l')
   -- local data, rerr = c:receive(225)

   print ("Receive:", data, rerr)
   c:close()
end

HDMIA1()

If the following only reads one line, I tried duplicating that line of code in the above a few time and in doing so it seems to read/return the line number the number of lines added relates to e.g so if I duplicate that line 3 times, it  seems to return just the 3rd line of information that the matrix sends back. (But each time it?s only one line of text that is returned)
  • '*l': reads a line of text from the socket. The line is terminated by a LF character (ASCII 10), optionally preceded by a CR character (ASCII 13). The CR and LF characters are not included in the returned line. In fact, all CR characters are ignored by the pattern. This is the default pattern;
« Last Edit: June 11, 2018, 03:38:19 pm by parkerc »

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Automatically adjust the read value returned via serial connection ?
« Reply #12 on: June 12, 2018, 02:46:44 pm »
Hi @akbooer,

Do you have any other thoughts on how to adjust the code to deal with different sized responses fro the matrix ?

Offline akbooer

  • Master Member
  • *******
  • Posts: 6153
  • Karma: +275/-69
  • "Less is more"
Re: Automatically adjust the read value returned via serial connection ?
« Reply #13 on: June 12, 2018, 06:20:38 pm »
As you have found, you can read the response line by line.  The trick is knowing when to stop.

Once again, the LuaSocket documentation is your friend...

http://w3.impa.br/~diego/software/luasocket/socket.html#select

You may use socket.select() to test if there's pending input.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2461
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Automatically adjust the read value returned via serial connection ?
« Reply #14 on: June 23, 2018, 05:02:37 am »
For reference, the information returned by the matrix when the read command is sent to it, is as follows. (Copy from luatest)

Quote
Print output
Send:     6     
Receive:     read Command OK
o01 i02 video on audio on CEC off
o02 i01 video on audio on CEC off
o03 i01 video on audio on CEC off
o04 i01 video on audio on CEC off
FW: V2.2.213
FPGA: V1.0.076
EDID: default     

I?m currently trying to read the second line and extract the first part, which I?m doing via the following code.

Code: [Select]
local sres, serr = c:send(string.char(0x72,0x65,0x61,0x64,0x0d,0x0a))
print("Send:", sres, serr)
local data, rerr = c:receive('*l')
local data, rerr = c:receive('*l')
luup.log (data)
print ("Receive:", data, rerr)
local result = string:match (data, "%o%d+%s%i%d+") or "error"
print ("Data=" ..result)

But currently I?m getting the following error, any ideas ?

Quote
Runtime error: Line 31: calling 'match' on bad self (string expected, got table)

Line 31 being.

Code: [Select]
local result = string:match (data, "%o%d+%s%i%d+") or "error"


FYI - I tested a few string match commands first to be sure it worked.



-- = string.match("o01 i02", '%o%d%d%s%i%d%d') = o01 i02
-- = string.match("o01 i02", '%o(%d+)%s%i(%d+)') = 01 02
-- = string.match("o01 i02", '%o%d+%s%i%d+') = o01 i02

« Last Edit: June 23, 2018, 05:06:54 am by parkerc »