Parsing incoming string of varying length help
zooeyl
Junior Member
Being a bit of a novice I have a question about incoming strings and extracting the information. I've used LEFT_STRING, RIGHT_STRING, MID_STRING before for various things, but I'm not sure how to go about retrieving the information for the following:
I have a large video matrix (512 in x 128 out) that has custom software inside that sends a serial string anytime a change has been made. I then take that string and extract the change and send a different string to an audio matrix. The string does have a start and end bit, but can have multiple changes. I need to be able to extract each change and send a string to the audio matrix. An example of a single change in the video matrix is as follows: 0x02M0001C00002L000000100x03 (the 0x02 is the start and the 0x03 is the end. In this case in need to extract M0001 and C00002 and can ignore the rest. I need to assign the M and C numbers to different variables. The matrix can also send multiple changes within the 0x02 - 0x03. It just repeats the M____C____L____ format within the start and stop bits. So it could look like: 0x02M0001C00003L00000100M0003C00010L000003000x03
I take the M number and the C number and translate that into a string that the audio matrix can use and send it. Any suggestions on extracting the information I need?
Thanks
I have a large video matrix (512 in x 128 out) that has custom software inside that sends a serial string anytime a change has been made. I then take that string and extract the change and send a different string to an audio matrix. The string does have a start and end bit, but can have multiple changes. I need to be able to extract each change and send a string to the audio matrix. An example of a single change in the video matrix is as follows: 0x02M0001C00002L000000100x03 (the 0x02 is the start and the 0x03 is the end. In this case in need to extract M0001 and C00002 and can ignore the rest. I need to assign the M and C numbers to different variables. The matrix can also send multiple changes within the 0x02 - 0x03. It just repeats the M____C____L____ format within the start and stop bits. So it could look like: 0x02M0001C00003L00000100M0003C00010L000003000x03
I take the M number and the C number and translate that into a string that the audio matrix can use and send it. Any suggestions on extracting the information I need?
Thanks
Comments
-
If M, C and L always have the same length you can use GET_BUFFER_STRING.
GET_BUFFER_CHAR(DATA.TEXT) // Pulls out the $02 sMyMVariable = GET_BUFFER_STRING(DATA.TEXT,5) // Pulls out M0001 sMyCVariable = GET_BUFFER_STRING(DATA.TEXT,6) // Pulls out C00003 sMyLVariable = GET_BUFFER_STRING(DATA.TEXT,9) // Pulls out L00000100
-
Thanks, M, C, & L are always the same length. I'll give that a try. Much appreciated.
-
zooeyl wrote:Thanks, M, C, & L are always the same length. I'll give that a try. Much appreciated.
This is another method, it will get all the M C L values and in the string... This method does not care how long the each M C L are. If the values of M C L exceed an integer, make all the integers LONGs.(***********************************************************) (* DEVICE NUMBER DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_DEVICE dvRS232 = 5001:1:0 (***********************************************************) (* VARIABLE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_VARIABLE VOLATILE CHAR cBuffer[1000]; (***********************************************************) (* SUBROUTINE/FUNCTION DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_FUNCTION DO_SOMETHING(INTEGER nM, INTEGER nC, INTEGER nL) { // do something with the informationm } DEFINE_FUNCTION ParseBuffer(CHAR cMsg[]) { STACK_VAR INTEGER M_VALUE; STACK_VAR INTEGER C_VALUE; STACK_VAR INTEGER L_VALUE; WHILE (FIND_STRING(cMsg,'M',1) && FIND_STRING(cMsg,'C',1) && FIND_STRING(cMsg,'L',1)) { REMOVE_STRING(cMsg,'M',1); M_VALUE = ATOI(cMsg); REMOVE_STRING(cMsg,'C',1); C_VALUE = ATOI(cMsg); REMOVE_STRING(cMsg,'L',1); L_VALUE = ATOI(cMsg); DO_SOMETHING(M_VALUE, C_VALUE, L_VALUE); } } (***********************************************************) (* STARTUP CODE GOES BELOW *) (***********************************************************) DEFINE_START CREATE_BUFFER dvRS232, cBuffer (***********************************************************) (* THE EVENTS GO BELOW *) (***********************************************************) DEFINE_EVENT DATA_EVENT[dvRS232] { STRING: { WHILE(FIND_STRING(cBuffer,"$03",1)); ParseBuffer(REMOVE_STRING(cBuffer,"$03",1)); } } (***********************************************************) (* END OF PROGRAM *) (* DO NOT PUT ANY CODE BELOW THIS COMMENT *) (***********************************************************) -
are you sure Jeff? I think you're missing a little bit of code in your ParseBuffer function.
something like . . .DEFINE_FUNCTION ParseBuffer(CHAR cMsg[]) { STACK_VAR INTEGER M_VALUE; STACK_VAR INTEGER C_VALUE; STACK_VAR INTEGER L_VALUE; WHILE (FIND_STRING(cMsg,'M',1)) { REMOVE_STRING(cMsg,'M',1); M_VALUE = ATOI(left_string(cMsg,find_string(cMsg,'C',1)-1)) REMOVE_STRING(cMsg,'C',1); C_VALUE = ATOI(left_string(cMsg,find_string(cMsg,'L',1)-1)) REMOVE_STRING(cMsg,'L',1); L_VALUE = ATOI(cMsg); DO_SOMETHING(M_VALUE, C_VALUE, L_VALUE); } } -
Jeff wrote:are you sure Jeff? I think you're missing a little bit of code in your ParseBuffer function.
something like . . .DEFINE_FUNCTION ParseBuffer(CHAR cMsg[]) { STACK_VAR INTEGER M_VALUE; STACK_VAR INTEGER C_VALUE; STACK_VAR INTEGER L_VALUE; WHILE (FIND_STRING(cMsg,'M',1)) { REMOVE_STRING(cMsg,'M',1); M_VALUE = ATOI(left_string(cMsg,find_string(cMsg,'C',1)-1)) REMOVE_STRING(cMsg,'C',1); C_VALUE = ATOI(left_string(cMsg,find_string(cMsg,'L',1)-1)) REMOVE_STRING(cMsg,'L',1); L_VALUE = ATOI(cMsg); DO_SOMETHING(M_VALUE, C_VALUE, L_VALUE); } }
Positive, ATOI will parse until it gets to the first non-numeric ascii char. No need to do the left strings... Try it, it works really cool!!!!! -
+1. The fact that ATOI behaves as it does (not evaluating anything beyond the first valid numeric characters it finds) saves a ton of extra coding, and allows for numbers coming in to be of any character length without screwing things up.
- ChipAMXJeff wrote:Positive, ATOI will parse until it gets to the first non-numeric ascii char. No need to do the left strings... Try it, it works really cool!!!!! -
Nifty . . . . learn something new every day.
OTOH, if he doesn't want an integer value, and he actually wants the characters, he'd need to do the left strings.
I'm gonna have to remember ATOI works that way though, thats a new one on me.
J -
Actually in your case, you can do a ITOA(ATOI(cMsg)) and get the ascii chars back with out the leading zeros... Just another neat trick....Jeff wrote:Nifty . . . . learn something new every day.
OTOH, if he doesn't want an integer value, and he actually wants the characters, he'd need to do the left strings.
I'm gonna have to remember ATOI works that way though, thats a new one on me.
J -
Thanks everybody. All I need are the numeric values, so the ATOI will work just fine.
-
LEFT_STRING is great when you're guaranteed to have a fixed-length string, (In the case of the OP, he'd be in luck) but you can use REMOVE_STRING on both fixed and variable length string responses and get what you need. In the case of "M____C____L____" - for example - you could do
REMOVE_STRING(cMsg,'M',1) M_VALUE = REMOVE_STRING(cMsg,'C',1) // "M_VALUE" is a character var here SET_LENGTH_STRING (M_VALUE,(LENGTH_STRING(M_VALUE)-1)) // Nuke the 'C' off the end
This will get you the characters you like regardless of how many there are between the 'M' and the 'C'.
If you don't care about leading zeros, AMXJeff's solution rocks - works great for getting verbose device feedback values up onto an indirect text button in a more human-friendly way.
- ChipJeff wrote:Nifty . . . . learn something new every day.
OTOH, if he doesn't want an integer value, and he actually wants the characters, he'd need to do the left strings.
J -
Thanks again for the help. Here's another scenario to make things one step more complicated. It is theoretically possible for the Video Matrix to send out multiple changes between the $02 and $03. For example:
$02M0001C00002L00000010M0002C00005L00000222$03
With multiple instances of M, C, & L how would you extract each instance individually? -
My code above handles multiple instances of M C L... The function dosomething will be triggered after each set of M C L have been parsed. So in your case below dosomething will be triggered twice. Hope this helps... See the same code below for ease of reading...
(***********************************************************) (* DEVICE NUMBER DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_DEVICE dvRS232 = 5001:1:0 (***********************************************************) (* VARIABLE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_VARIABLE VOLATILE CHAR cBuffer[1000]; (***********************************************************) (* SUBROUTINE/FUNCTION DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_FUNCTION DO_SOMETHING(INTEGER nM, INTEGER nC, INTEGER nL) { // do something with the informationm } DEFINE_FUNCTION ParseBuffer(CHAR cMsg[]) { STACK_VAR INTEGER M_VALUE; STACK_VAR INTEGER C_VALUE; STACK_VAR INTEGER L_VALUE; WHILE (FIND_STRING(cMsg,'M',1) && FIND_STRING(cMsg,'C',1) && FIND_STRING(cMsg,'L',1)) { REMOVE_STRING(cMsg,'M',1); M_VALUE = ATOI(cMsg); REMOVE_STRING(cMsg,'C',1); C_VALUE = ATOI(cMsg); REMOVE_STRING(cMsg,'L',1); L_VALUE = ATOI(cMsg); DO_SOMETHING(M_VALUE, C_VALUE, L_VALUE); } } (***********************************************************) (* STARTUP CODE GOES BELOW *) (***********************************************************) DEFINE_START CREATE_BUFFER dvRS232, cBuffer (***********************************************************) (* THE EVENTS GO BELOW *) (***********************************************************) DEFINE_EVENT DATA_EVENT[dvRS232] { STRING: { WHILE(FIND_STRING(cBuffer,"$03",1)); ParseBuffer(REMOVE_STRING(cBuffer,"$03",1)); } } (***********************************************************) (* END OF PROGRAM *) (* DO NOT PUT ANY CODE BELOW THIS COMMENT *) (***********************************************************)zooeyl wrote:Thanks again for the help. Here's another scenario to make things one step more complicated. It is theoretically possible for the Video Matrix to send out multiple changes between the $02 and $03. For example:
$02M0001C00002L00000010M0002C00005L00000222$03
With multiple instances of M, C, & L how would you extract each instance individually?
Categories
- All Categories
- 2.5K AMX General Discussion
- 922 AMX Technical Discussion
- 514 AMX Hardware
- 502 AMX Control Products
- 3 AMX Video Distribution Products
- 9 AMX Networked AV (SVSI) Products
- AMX Workspace & Collaboration Products
- 3.4K AMX Software
- 151 AMX Resource Management Suite Software
- 386 AMX Design Tools
- 2.4K NetLinx Studio
- 135 Duet/Cafe Duet
- 248 NetLinx Modules & Duet Modules
- 57 AMX RPM Forum
- 228 MODPEDIA - The Public Repository of Modules for Everyone
- 943 AMX Specialty Forums
- 2.6K AMXForums Archive
- 2.6K AMXForums Archive Threads
- 1.5K AMX Hardware
- 432 AMX Applications and Solutions
- 249 Residential Forum
- 182 Tips and Tricks
- 146 AMX Website/Forums
