Your Universal Remote Control Center
RemoteCentral.com
Philips Pronto Professional Forum - View Post
Previous section Next section Up level
Up level
The following page was printed from RemoteCentral.com:

Login:
Pass:
 
 

Topic:
Async RS-232 status updates
This thread has 8 replies. Displaying all posts.
Post 1 made on Monday February 8, 2010 at 15:15
n2hifi
Long Time Member
Joined:
Posts:
August 2007
192
I have an RS-232 device that gives a status update about once a minute. I basically want to parse the data it gives and display it. From the developer guide it says the data is buffered to the RFX-9600 when it comes in so I want to make sure I am moving in the most efficient direction.

Supposing I have already defined 's' as my serial port and set s.onData = someFunction(){}

I can then call s.Match("","\x5D",250) every minute and it would pull the data that is buffered (provided the terminator on the buffered data is "\x5D").

Something seems inefficient here though, like I am missing something incredibly simple. Is there a better way to sit and wait for data asynchronously?

The developer guide shows and AVReceiver example, but it appers to be synchronous.

function PollAVReceiver()
{
d = s.match("", "\r", 0); // Synchronous read with timeout=0
.../* parse d for data to be displayed */
scheduleAfter(1000, PollAVReceiver); // Schedule next poll
};
PollAVReceiver (); // Start polling

Is this the way to go?
Mark Olsen, CTS
Cannon Design
Post 2 made on Monday February 8, 2010 at 17:40
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,999
There is no way other than doing a receive() or match() polling operation. Also note that if you transmit data to the serial port using send() or match(), that the existing buffer is cleared.

This behavior makes it more difficult (read as not 100% reliable) to do full-duplex communication as prior to a send, you must always do receive() or match() prior to send() or match() and there is always a small window that can occur where you blow away data that is in the buffer.

Assuming you are using async model for serial port, you can do:

s.receive(1024,125); // initial read to drain the buffer waiting only 125ms.
// data will be delivered asynchronously either in onData() or onTimeout()
// callback - onTimeout will be called if less than 1024 bytes of data.
s.match(toSend,"\r",1000);

Yes, to me, this is very quirky. Almost makes for easier programming to do the serial operation synchronously. In fact, that is exactly what I do with my X10 module. :-)
Lyndel McGee
Philips Pronto Addict/Beta Tester
Post 3 made on Tuesday February 9, 2010 at 11:13
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,999
Also note that Serial Ports 3 and 4 share a single UART and therefore are useful pretty much only for 1-way serial communication if both ports are in use. If you require 2-way communication rely on Ports 1 and 2 and if you must resort to using Port 3 or 4 for 2 -way , ensure that the other port that shares the UART (3 or 4) is not used.
Lyndel McGee
Philips Pronto Addict/Beta Tester
OP | Post 4 made on Wednesday February 10, 2010 at 09:23
n2hifi
Long Time Member
Joined:
Posts:
August 2007
192
So if I understand you right Lyndel, my code:

port_buffer = envPort.match("","\x5D",0);

would actually not work because if there were more than one status update in the buffer I would only be reading the first one and then would clear the entire buffer. Is that correct? I should actually be pulling the entire buffer and parsing from there:

port_buffer = envPort.receive(1024,125);

In this case I could theortically receive a half message. So I guess i need to 'handle' that.
Mark Olsen, CTS
Cannon Design
Post 5 made on Wednesday February 10, 2010 at 10:17
buzz
Super Member
Joined:
Posts:
May 2003
4,382
I would create a master status vector for the 2-way devices. Usually, it is possible to determine why a synchronous or asynchronous status has been returned and the appropriate vector component can be updated. The vector components would always contain the latest available data that program elements can interrogate as needed. While program elements would not need to request, then wait for data, no scheme can be absolutely bomb proof because an important reply could have been flushed from the buffer.
Post 6 made on Wednesday February 10, 2010 at 13:17
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,999
On February 10, 2010 at 09:23, n2hifi said...
So if I understand you right Lyndel, my code:

port_buffer = envPort.match("","\x5D",0);

would actually not work because if there were more than one status update in the buffer I would only be reading the first one and then would clear the entire buffer. Is that correct? I should actually be pulling the entire buffer and parsing from there:

port_buffer = envPort.receive(1024,125);

In this case I could theortically receive a half message. So I guess i need to 'handle' that.

No, you are incorrect. The first match you list above does not send anything (you supplied empty string or null as first parameter) so it simply does a receive and does NOT clear the buffer prior to the receive.

Please have a look at the match and send documentation in Appendix A/B of the Dev Guide as it explains in more detail.

However, as you note, doing a receive of 1024 bytes is definitely faster as you will get everything in one operation but may have to deal with partial messages.

I think the buffer size is 1024 bytes of RFX9600 but you can only receive 512 bytes at one time IIRC. Again, I think you will want to see the Dev Guide on this limit as it has been a while since I looked at it.

If that is the case,

var data = s.receive(512,125);
data += s.receive(512,125);

will do the trick.
Lyndel McGee
Philips Pronto Addict/Beta Tester
Post 7 made on Wednesday February 10, 2010 at 13:29
Barry Gordon
Founding Member
Joined:
Posts:
August 2001
2,157
I do a lot of RS232 comm work but none of it using extenders or Prontoscript directly. I prefer a PC with a good baseline model for handling serial communications. Independent of what the protocol documents say I always do the following:

Specify an interrupt as each character comes in, this rarely happens on a per character basis but generally with some number of characters depending on line speed and how the OS is handling interrupts. Most of the time for fast line speeds (38.4 and up) I get a full message, but under many conditions I get either multiple messages, or partial messages.

When the interrupt comes in grab the buffer as it stands and add it to an internal buffer via concatenation.

If there is a unique termination sequence, then while that sequence is in the buffer, process the buffer contents from the first byte up to the termination sequence in a loop.

If the message has some fixed length with or without an internal count do a similar process but utilize the count or size information to determine a physical message.

Beware of protocols that claim that there is a unique termination sequence but include binary data such as a 16 or 32 bit number in the message. The number may contain bytes that mimic the termination sequence.

How to do this in ProntoScript with an extender is Lyndel's field of expertise.
Post 8 made on Wednesday February 10, 2010 at 17:40
Lyndel McGee
RC Moderator
Joined:
Posts:
August 2001
12,999
And, I missed something in my reply above regarding your last question. As Barry points out, you can get incomplete messages and/or multiple messages. Yes, your code must handle those conditions.

I usually do something as follows:

// serial port.
var mySerialPort=CF.extender[0].serial[0]; // port #1

// Buffer defined at activity level (I usually attach buffer to serial port).
var currentBuffer = '';
// if attaching field to port - mySerialPort.currentBuffer = '';
function processData(data)
{
if (!data)
{
// we got timeout with no data.
return;
}
// if attached to serial port - this.currentBuffer += data;
currentBuffer += data;
// splitData is a custom function to extract individual messages from
// all data received thus far.
var o = splitData(currentBuffer) // returns an object with 2 fields: complete
// msgs array and remaining data, if any.
// if no remaining data, return array plus
// empty string.

var completeMsgs = o.completeMsgs;
// if attached to serial port - this.currentBuffer = o.partialData;
currentBuffer = o.partialData;
if (completeMsgs)
{
var index = 0;
var len = completeMsgs.length;
while (index < len)
{
var message = completeMsgs[index];
// logic to process single message;
index++;
}
}
}

mySerialPort.onData = processData;
mySerialPort.onTimeout = processData; // see note below.

Note that onTimeout(data) will also be fired if timeout condition occurs with any data received up to point of timeout so you should be prepared to write a single processData(data) function that is called from both the onData() and onTimeout() callbacks of the Serial Port.

Last edited by Lyndel McGee on February 10, 2010 17:49.
Lyndel McGee
Philips Pronto Addict/Beta Tester
Post 9 made on Wednesday February 10, 2010 at 18:27
sWORDs
Long Time Member
Joined:
Posts:
November 2006
373
I totally agree with Barry on not using extenders for twoway communication. I've actually just bought some Crestron Control Systems to use. (You can have 16x IR, 16x relay, 6x com for $350 on Ebay)

A few other reasons why extenders are not perfect:
1) An extender can only do one thing on one port at a time, it will lock when doing an ir command while running a rs232 module, so you'll need to catch this (which you can't really catch, because all send errors are the same "PanelError") or make sure nothing else runs on the extender when doing async.
2) An extender does not queue, you'll need to do it, so forget about two modules from different builders working together on the same extender.
3) An extender can't run scripts, so the remote will do all the heavy work.
4) An extender can't do multiple sockets (only one remote at the same time).
5) An extender is slow in rs232 communication from prontoscript.
6) An extender can't do tcp/ip (so you'll need to close sockets when using multiple remotes)
7) An extender can't store variables.
8) An extender can't build ir commands.
9) An extender only works with Pronto's, so no PC, iPhone or anything.

My Denon modules can recover most of the above problems, but I still don't like having to work around them.

This is why I'll be using Pronto<->Crestron until Philips releases their processor in the 4th quarter.

Last edited by sWORDs on February 11, 2010 14:04.


Jump to


Protected Feature Before you can reply to a message...
You must first register for a Remote Central user account - it's fast and free! Or, if you already have an account, please login now.

Please read the following: Unsolicited commercial advertisements are absolutely not permitted on this forum. Other private buy & sell messages should be posted to our Marketplace. For information on how to advertise your service or product click here. Remote Central reserves the right to remove or modify any post that is deemed inappropriate.

Hosting Services by ipHouse