Syncronous receive transmit

If you have devices that reply with the same string from different commands and those replies need to be treated differently what is the best way to handle that?

I am currently using to handle the received string then using a global variable to branch depending on the actual command sent.

Is this the best way to approach this or should I use intercept instead or maybe another mechanism all together?

That’s pretty much what I do, except the global variable is a function ptr that I set prior to writing the command on the bus. There’s also logic to remove this ‘handler’ if data isn’t received in enough time… But that can leave you in a doddgy situation…

@guessed

Sorry having troubling visualizing can you point me at some of your code where you did this. I am not convinced that mine is very robust I think it could easy get out of sync.

Thanks

Not sure mine is robust either…
http://code.mios.com/trac/mios_iorelay/browser/trunk/I_IORelay1.xml

I need to change my code so thatmultibyte handlers only write back their ‘state’ (to Vera) when the last byte is received. This will better handle any lost-data situations… I also assume that the stream will correct itself at some point… Which is the dodgy part I was referring to. Unfortunately there is no way to send a reset command for this (state full) protocol.

Btw, what are you trying to interface to that has a state full protocol?

PS: never realized the TZ overlap between WA and the US was so reasonable in the early am.

I do the same as @guessed. I maintain a global array of function pointers indexed by the message type (a number). Message arrives, I call handlersid. I can easily add or remove functions to/from the handlers array to alter what I consider to be the set of expected responses.

Using Lua functions as first-class objects is one of those important bits of the language that you will struggle with until you grok it, and then you will wonder how you ever managed without it.

@guessed
Tend to do this hobby stuff very late at night when my wife and kids are all asleep (At work right now so probably shouldn’t be on the forum).

@futzle
Looked at code that guessed pointed me too and I can tell you for certain that I don’t grok it :slight_smile: so will be spending more time trying to get my head around what/how you do it.

This is for a DALI serial interface and not sure it is stateful more like stateless (had to look that one up on wikipedia :slight_smile: ) but you get the same response from multiple commands so need to know what the command was so correct action can be taken. Now I am more confused then ever and not even sure I am asking the question in the correct way or that the subject heading is the correct terminology.

@zoot1612,
What you’re effectively building is a little state machine. Just before you send something, you setup the SM to be able to handle the type of response you’re expecting to get back.

You could just as readily do this by setting a String value for the state, prior to sending the request, but then you’d end up with a big ol’ IF-THEN-ELSEIF-ELSEIF… END Ladder in the response ([tt][/tt]) block that decodes this “string”, and calls the appropriate chunk of code.

So, to simplify things, you set a “function” as the state before sending something, and then call that function when the response comes in.

It just saves the IF-Ladder, and the cost of all the evals.

If you happen to have it, you can lookup the “State Machine” pattern in the gang of four book “Design Patterns, Elements of Reusable…”. I love this book, very handy stuff, and expressed in easy to read terms. I read this extensively when I was learning to Program in C and Java.

PS: IORelay is extra complicated by the fact that each handler has to handle the response data byte-by-byte, through single-byte [tt][/tt] calls. Your protocol might be easier, and then it wouldn’t require this complexity.

@guessed
Thanks managed to get most of it figured from your IORelay plugin.

I was having trouble with data disappearing so tried another tack but still having the same issue. Is there something fundamentally wrong with the following code or is it the connected device.

Thanks in advance.

[code]local function r8nStartupRxTx(command)

local receivedByte = 0
local byteCount = 0
luup.io.intercept()

if(luup.io.write(command) == false) then
	return false
else
luup.sleep(1000)
	while(byteCount < 3) do
		local data = tonumber(string.byte(luup.io.read()))
		if (data ~= nil) then
			log(":r8nStartupRxTx:data:" .. string.format("%02X",data))
			receivedByte = (receivedByte * 256) + data
			byteCount = (byteCount + 1)
			luup.io.intercept()
		end
	end
	return receivedByte
end

end[/code]

From memory, intercept only works for 1 call to read, whether it returns data or not. I avoid using intercept altogether since, depending upon how calls are interleaved, there are windows of time where data might not be caught. YMMV

Aaargh
Two devices with different serial speeds and response times and I have to use two completely different implementations.

@guessed
Thanks for your help.