Author Topic: Act on response from usb to serial device command.  (Read 1908 times)

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #15 on: September 08, 2017, 10:37:50 am »
I'm not sure that this very iterative approach is quite the way forward.

I'm just a simple man, with limited (bit thankfully improving) Lua abilities - i'm not sure what is the best way - step by step felt the best :)

The code structure we're now discussing has evolved quite a bit from where I started - which is good as it helps me to learn. But it must be painful for everyone else reading this thread :)

Tell you what - I'll try and pull the whole thing together (and sadly I only get pocket of time to focus on tweaking things on my Vera due to myjob) - I will try to keep it simpler too for now and look to make a new connection every time.
« Last Edit: September 08, 2017, 10:52:56 am by parkerc »

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #16 on: September 08, 2017, 11:41:35 am »
Ok, I think I have all the elements now, I'm just not able to link/pass elements between the functions - Help :-(

To try and keep this simple - the workflow aims to be  - 1) HDMI Matrix command sent, 2) response from matrix captured/assessed, and 3) appropriate message presented.

Code: [Select]
local function send_command_to_hdmi_matrix(...)
   local socket = require("socket")
   host = "192.168.1.204"
   c = assert(socket.connect(host, 4002))
   c:settimeout(5)
   local sres, serr = c:send(string.char(...))
   local data, rerr = c:receive(205)
   local result = data: match "Status code:(%d+)" or "error"
   print ("Receive:", data, rerr)
   print ("" ..result)
   c:close()
end

local function interpret_reply_from_hdmi_matrix()
   message = {
     ["error"] = "Something else happened, it likely failed",
     ["100011111110101"] = "Input 1 was selected successfully for Output A",
     ["100021111110101"] = "Input 2 was selected successfully for Output A",
     ["100031111110101"] = "Input 3 was selected successfully for Output A",
     ["100041111110101"] = "Input 4 was selected successfully for Output A",
     ["100024231110101"] = "Port scan completed successfully",
     -- extend this with new codes when needed
   }
end

local function present_results_of_hdmi_matrix_interaction()

   print (message[result] or "Unexpected status code received")

   local handle = luup.task("Octava HDMI Matrix: " .. result, 1, "Vera", -1)
        luup.call_delay("clearTaskMsg",2,handle)
   
-- Help - I need the luup.task to use the text that's looked up via the interpret_reply_from_hdmi_matrix function e.g ""Input 1 was selected successfully for Output A","

end

local function clearTaskMsg(strHandle)
        luup.task("",4,"",tonumber(strHandle))
end


send_command_to_hdmi_matrix(0x02,0x32,0x31,0x32,0x03)
« Last Edit: September 08, 2017, 11:46:29 am by parkerc »

Offline akbooer

  • Master Member
  • *******
  • Posts: 5812
  • Karma: +249/-69
  • "Less is more"
Re: Act on response from usb to serial device command.
« Reply #17 on: September 08, 2017, 12:40:03 pm »
Well, nearly there.  You just had to link it all together with the appropriate parameter passing...

Code: [Select]
local host = "192.168.1.204"
local port  = 4002

local socket = require("socket")


local function send_command_to_hdmi_matrix(...)
   local c = assert(socket.connect(host, port))
   c:settimeout(5)
   local sres, serr = c:send(string.char(...))
   local data, rerr = c:receive(205)
   local result = data: match "Status code:(%d+)" or "error"
   print ("Receive:", data, rerr)
   print ("" ..result)
   c:close()
   return result    -- return the result
end

local function interpret_reply_from_hdmi_matrix(status)
  local message = {
     ["error"] = "Something else happened, it likely failed",
     ["100011111110101"] = "Input 1 was selected successfully for Output A",
     ["100021111110101"] = "Input 2 was selected successfully for Output A",
     ["100031111110101"] = "Input 3 was selected successfully for Output A",
     ["100041111110101"] = "Input 4 was selected successfully for Output A",
     ["100024231110101"] = "Port scan completed successfully",
     -- extend this with new codes when needed
   }
  return message[status] or "Unexpected status code received"
end

local function present_results_of_hdmi_matrix_interaction(result)
  print (result)
  local handle = luup.task("Octava HDMI Matrix: " .. result, 1, "Vera", -1)
        luup.call_delay("clearTaskMsg",2,handle)
end

function clearTaskMsg(strHandle)  -- this HAS to be non-local for call_delay to work
  luup.task("",4,"",tonumber(strHandle))
end

-- here's your main 'workflow'

local status = send_command_to_hdmi_matrix(0x02,0x32,0x31,0x32,0x03)
local message = interpret_reply_from_hdmi_matrix(status)
present_results_of_hdmi_matrix_interaction(message)

-- done
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 4x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #18 on: September 08, 2017, 01:10:26 pm »
Wow !! - It works ... ;D  (Thanks so much)

I have to be honest, I'm struggling to understand how all the functions are connected, plus it looks like you have done it so it sort of reverse order ?

It seems you start off by calling the function called present_results_of_hdmi_matrix_interaction(message) outright  - which in turn calls the function assigned to 'message' which is interpret_reply_from_hdmi_matrix(status) - and then that calls the final function which has been assigned to 'status', and has the required attribute in it status = send_command_to_hdmi_matrix(0x02,0x32,0x31,0x32,0x03)

Am i close ?
« Last Edit: September 08, 2017, 01:31:07 pm by parkerc »

Offline akbooer

  • Master Member
  • *******
  • Posts: 5812
  • Karma: +249/-69
  • "Less is more"
Re: Act on response from usb to serial device command.
« Reply #19 on: September 08, 2017, 01:37:54 pm »
No, not at all.

The functions, which can be defined in any order, are called by the sequence I labelled as your workflow, at the bottom of the code.

Definitely time to learn Lua programming properly by reading this: https://www.lua.org/pil/
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 4x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #20 on: September 08, 2017, 01:58:33 pm »
??? - I wish I was better at reading, i'm sadly not a text/book person :-(  I do my very best to dip in and out of specifc chapters in the Lua manaul, but the wording just grates on me, as I struggle to understand it all - so far I seem to learn better by experimenting and using real world testing/examples..

QQ - As the others in the workflow at the bottom start with 'local' - doesn't that me you are calling the present_results_of_hdmi_matrix_interaction() first ?
« Last Edit: September 08, 2017, 02:02:15 pm by parkerc »

Offline akbooer

  • Master Member
  • *******
  • Posts: 5812
  • Karma: +249/-69
  • "Less is more"
Re: Act on response from usb to serial device command.
« Reply #21 on: September 08, 2017, 02:32:02 pm »
No, local has nothing to do with it.  Statements are executed in order (unlike some other languages, like Prolog.)

A function statement, is just the same.  In fact

Code: [Select]
function f(a)
 return 2*a
end

is actually just shorthand for

Code: [Select]
f = function (a)
 return 2*a
end

...a statement which defines what the function actually is.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 4x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #22 on: September 08, 2017, 02:44:39 pm »
OK, I think I understand - I had understood 'local' to be a way to make something easier to reference/call within your code - e.g to allocate a keyword to a retrievable variable or function.

What confused me was within the Workflow section, you had only applied 'local' to the beginning of 2 of the 3 functions, therefore I assumed the one that was not designated as local would be invoked, so would run first.

Code: [Select]
-- here's your main 'workflow'

local status = send_command_to_hdmi_matrix(0x02,0x32,0x31,0x32,0x03)
local message = interpret_reply_from_hdmi_matrix(status)
present_results_of_hdmi_matrix_interaction(message)

-- done

So I hope I have it - is what you're saying - that just the association of a 'local' reference word e.g status, message etc. will still result in it being executed ?

if that's the case, why were all 3 not designated as being local e.g

Code: [Select]
-- here's your main 'workflow'

local status = send_command_to_hdmi_matrix(0x02,0x32,0x31,0x32,0x03)
local message = interpret_reply_from_hdmi_matrix(status)
local results = present_results_of_hdmi_matrix_interaction(message)

-- done

Sorry - I really must be driving you crazy :-)
« Last Edit: September 08, 2017, 02:46:28 pm by parkerc »

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #23 on: September 08, 2017, 02:48:20 pm »
Would you believe it, it seems the Status Code: values can change after a port scan or if more than one output is in action, but thankfully I think I have found something that is more consistent within the response, so have updated the code.

Code: [Select]
local host = "192.168.1.204"
local port  = 4002

local socket = require("socket")


local function send_command_to_hdmi_matrix(...)
   local c = assert(socket.connect(host, port))
   c:settimeout(5)
   local sres, serr = c:send(string.char(...))
   local data, rerr = c:receive(205)
   local result = data: match "S(%d+)E" or "error"
   print ("Receive:", data, rerr)
   print ("" ..result)
   c:close()
   return result    -- return the result
end

local function interpret_reply_from_hdmi_matrix(status)
  local message = {
-- error
["error"] = "Something else happened, it likely failed",
-- Output A
["211"] = "Input 1 was selected successfully for Output A",
["212"] = "Input 2 was selected successfully for Output A",
["213"] = "Input 3 was selected successfully for Output A",
["214"] = "Input 4 was selected successfully for Output A",
-- Output B
["221"] = "Input 1 was selected successfully for Output B",
["222"] = "Input 2 was selected successfully for Output B",
["223"] = "Input 3 was selected successfully for Output B",
["224"] = "Input 4 was selected successfully for Output B",
-- Output C
["231"] = "Input 1 was selected successfully for Output C",
["232"] = "Input 2 was selected successfully for Output C",
["233"] = "Input 3 was selected successfully for Output C",
["234"] = "Input 4 was selected successfully for Output C",
-- Output D
["241"] = "Input 1 was selected successfully for Output D",
["242"] = "Input 2 was selected successfully for Output D",
["243"] = "Input 3 was selected successfully for Output D",
-- Port Scan
["001"] = "Port scan completed successfully",
-- LED OFF
["004"] = "Port scan completed successfully",
-- LED ON
["003"] = "Port scan completed successfully",
-- Power OFF
["006"] = "Port scan completed successfully",
-- Power ON
["005"] = "Port scan completed successfully",

}
  return message[status] or "Unexpected status code received"
end

local function present_results_of_hdmi_matrix_interaction(result)
  print (result)
  local handle = luup.task("" .. result, 1, "Octava HDMI Matrix", -1)
        luup.call_delay("clearTaskMsg",5,handle)
end

function clearTaskMsg(strHandle)  -- this HAS to be non-local for call_delay to work
  luup.task("",4,"",tonumber(strHandle))
end

-- here's your main 'workflow'
local status = send_command_to_hdmi_matrix(0x02,0x32,0x32,0x34,0x03)
local message = interpret_reply_from_hdmi_matrix(status)
present_results_of_hdmi_matrix_interaction(message)

-- done

It seems there are these SxxxE values returned too when a successful request is completed. So I have updated those within the code above. using this expression seems to work "local result = data: match "S(%d+)E" or "error""

Quote
LuaTest 1.5.2

Lua file: /nas/luatest/matrix-startup4.lua

Results
No errors
Runtime: 252.1 ms
Code returned: nil

Print output
Receive:     ????????
ser2net port 4002 device /dev/ttyUSB0 [9600 N81] (Debian GNU/Linux)

S224E

Status code:100014131110101

**Refer to Install Guide or FAQ (www.octavainc.com)for serial control protocol.
« Last Edit: September 08, 2017, 02:51:49 pm by parkerc »

Offline akbooer

  • Master Member
  • *******
  • Posts: 5812
  • Karma: +249/-69
  • "Less is more"
Re: Act on response from usb to serial device command.
« Reply #24 on: September 08, 2017, 03:23:04 pm »
Quote
if that's the case, why were all 3 not designated as being local e.g

The first two were, the third does not return a result.  See my original code.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 4x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #25 on: September 08, 2017, 06:07:25 pm »
Quote
if that's the case, why were all 3 not designated as being local e.g

The first two were, the third does not return a result.  See my original code.


Ok, and by 'result' you mean that particular function did not generate anything that was needed by anything else , it was just a function to display the required notification message.?

I still need to get my head around how a function's argument/parameter () is used. It seems you can specify a value, call a local element or provide guidance on values you want. I've read this article (https://www.tutorialspoint.com/lua/lua_functions.htm) many times to help but it's a slow process. :)

Offline jswim788

  • Hero Member
  • *****
  • Posts: 676
  • Karma: +43/-2
Re: Act on response from usb to serial device command.
« Reply #26 on: September 08, 2017, 06:22:08 pm »
Ok, and by 'result' you mean that particular function did not generate anything that was needed by anything else , it was just a function to display the required notification message.?
The usage of a function is up to you.  You can have a statement:
Code: [Select]
myFunc(var1, var2)Although you may have defined a return value for myFunc, here it is ignored.  You didn't put the return value in a variable.

Or you can have an expression:
Code: [Select]
result = myFunc(var1, var2)In this case, you do use the result, and it is put into the global variable named "result".  But likely you don't want to use a global variable, you want to use a local variable.  So now add the "local" to the result variable:
Code: [Select]
local result = myFunc(var1, var2)

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #27 on: September 10, 2017, 04:47:50 am »
Thanks for that @jswim788, (and also for everyone's else's patience on this)

Things are getting a bit clearer, but it's just not as easy as I had hoped it would be to grasp. :(. - It really is like learning another language   :)

It's perhaps the types of things you can put into the brackets/parentheses that confuses me. As it seems it can be a value e.g.(0x20, 0x30, 0x31), or it can been a reference word to a local variable or a function e.g  (deviceID) or it can have multiple references all comma separated e.g  (this, that, theother).

It's the rule of what to use where and when
« Last Edit: September 10, 2017, 04:58:12 am by parkerc »

Offline parkerc

  • Sr. Hero Member
  • ******
  • Posts: 2386
  • Karma: +33/-45
  • Life Moves Pretty Fast....
    • Node Central
Re: Act on response from usb to serial device command.
« Reply #28 on: September 10, 2017, 05:08:16 am »
This is what I was asking previously.  If you want to make a new connection each time, you need the connect within the function.  I wouldn't use assert.  As it is you've got the variable 'host' undefined at the point it's used.

As a side learning point - If I wanted to have a permanent open connection with the HDMI Matrix, would this be the correct approach?  e.g move the assert socket connect out of the function and delete the close() request.

Code: [Select]
local host = "192.168.1.204"
local port  = 4002
local socket = require("socket")
local c = assert(socket.connect(host, port))

local function send_command_to_hdmi_matrix(...)
   local sres, serr = c:send(string.char(...))
   local data, rerr = c:receive(205)
   local result = data: match "S(%d+)E" or "error"
   print ("Receive:", data, rerr)
   print ("" ..result)
   return result    -- return the result
end

Offline akbooer

  • Master Member
  • *******
  • Posts: 5812
  • Karma: +249/-69
  • "Less is more"
Re: Act on response from usb to serial device command.
« Reply #29 on: September 10, 2017, 05:21:51 am »
Basically, yes.

You may run into several problems, though:
  • your device may not actually keep the connection open
  • since you haven't read the whole of the output, you may not receive what you think

However, if a permanent connection does work, you could possibly abandon the direct use of sockets and use instead the luup.io functions.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 4x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.