Host Engineering Forum
General Category => Do-more CPUs and Do-more Designer Software => Topic started by: RBPLC on November 18, 2019, 10:44:51 PM
-
Let's say I had a .txt file that I wanted to import using the FILEREAD command. The text file was structured like: 1,0,1,1\r and I wanted to import 1,0,1,1 into locations C1, C2, C3 AND C4. Is there any way to do this directly or would I have to import the file as ASCII text and convert this string using a string command to get the bits into the C locations?
-
See the attached export project file. It runs stand alone in the Simulator.
It takes a string with CSV data and parses it for real numbers and sticks the values into a block of real values. It has 2 parts, the first program code block Tokenize tokenizes the values - separates the CSV text data into an array of individual strings. The ParseToken program code block goes through that array of string tokens and calls STRTOREAL go generate the REAL values and sticks those in a REAL data block.
You would still need to do the FILEREAD to get the line of data out of the file, but then launch those 2 code blocks.
-
Thanks franji. I'll try this out and see what I can do with it. Do you see this as being something that could be natively (could be directly accomplished) supported at some point? I was looking at this as a potential to "batch load" a profile to control some lighting relays that would automatically be adjusted at pre-defined intervals. This approach would be similar to loading a recipe from an HMI at predefined intervals. Is there some other built-in function that I'm missing that could be used to accomplish the same thing?
-
It's already there via JSON. CSV is OK, but you must know the schema of each column/token. Is it a bit? Integer? Real? Text? To come up with some kind of generic CSV parser would be very difficult.
I recommend you read up on JSON. JSON handles it much better than CSV, and Do-more already supports it!
JSON supports arrays and/or fields and you can nest them. For flat CSV, you can easily implement it as an array of 0/1 bits:
[0, 1, 1, 0]
or even as Boolean (Do-more supports BOTH)
[false, true, true, false]
And even better, if it's a profile/recipe, you can store it as "field"/colon/value list:
{
"CookTemp" : 42,
"CookTime": 60,
"UseIngredientA": true,
"UseIncredientB": false
}
-
Thanks for the info, I'll look into JSON more. I'm assuming you would then utilize the JSONPARSE command?
-
Thanks for the info, I'll look into JSON more. I'm assuming you would then utilize the JSONPARSE command?
Exactly. We added ability to 2.6 in JSONPARSE to parse the value straight to a bit, integer, real, or string element.
2.5 only parses it to a string, then you have to do the STR2INT instruction on the parsed string value). 2.6 eliminates that 2nd step.
Not sure how you are generating your text file, but if you could somehow put brackets around it - anywhere, it can work.
This can work:
[
1, 1, 0
]
white space means nothing (except inside the field name double quotes)
-
Franji,
I was reading up on JSON and think I understand the basics. I was trying to use the JSONPARSE in conjunction with a for loop to extract bits and assign them to C registers. Here's what I've got (see image attached for reference):
I'm attemting to parse JSON string SS1. For this example this is a 10 length array of boolean values. I'm trying to run through string SS1 using a for loop with index stored in V10 going from 0 to 9. I've selected "0-based Array/Field Index" and set this value to V10. I would like to store the bits in registers C100-C109. The problem that I'm having is that I can't specify C[100+V10] to correspond with the loop index. What am I missing in trying to write the bits into C100-C109 using the syntax C[100+V10]?
-
What am I missing in trying to write the bits into C100-C109 using the syntax C[100+V10]?
That type of indirect reference is limited to C[V10+63] if I'm not mistaken. Otherwise it maybe limited to 31. I wish it was more flexible than that, but such is life.
If necessary, sometimes I do a MATH instruction in the loop to do V11 = V10+100, then you can reference C[V11].
Hope that helps!
-
Thanks Bolt. It didn't occur to me to use a MATH function to get the index I wanted.
-
MATH Result array index can be full MATH expressions themselves.
So, stick the result of the JSONPARSE into a temp C bit, say C42, then do a MATH with C[V10 + 100] in the Result field, and just "C42" in the expression.
MATH C[V10 + 100] "C42"
-
What am I missing in trying to write the bits into C100-C109 using the syntax C[100+V10]?
That type of indirect reference is limited to C[V10+63] if I'm not mistaken. Otherwise it maybe limited to 31. I wish it was more flexible than that, but such is life.
If necessary, sometimes I do a MATH instruction in the loop to do V11 = V10+100, then you can reference C[V11].
Hope that helps!
We?re already cramming 10 pounds into a 5 pound bag. Six bits was all that was available for the displacement. We are currently spec-ing the Son of Do-more engine that will be able to do simple expressions for virtually every input parameter, in addition to very deep UDTs and multidimensional arrays. Limits like this will be gone forever.
-
So I've got the JSON parsing working. Now I've got another issue. I've got to first get my JSON structured text into the controller. I'm doing this using the FILEREAD command to read in a .txt file. The problem is my JSON structured text will wind up being more than 1024 characters long for the full implementation. Would there be a straightforward way to iteratively parse sections of my JSON formatted text file to import sections of it at a time? I realize I could break my text file up into multiple files that don't exceed 1024 characters but I would like to keep it one file if possible.
-
Instead of using a STRING, us a BYTE Data Block.
Create a new BYTE block called MyData that's 10,000 in length (or whatever max length you think you need).
Use that data block in your FILEREAD and in your JSONPARSE instruction.
-
Franji,
See attached photo. I created the MyData unsigned byte block that is MyData0-9999. I still seem to be running into the same issue with import length. I set the "Buffer Size in Bytes" to the maximum of 1024. I can't seem to import anymore than 1024 characters out of my JSON text file.
-
FILEREAD can be called more than once to fill the buffer.
-
I guess the best way to do this is using the FILESEEK command to pick up reading the file where it left off on the last FILEREAD?
-
I guess the best way to do this is using the FILESEEK command to pick up reading the file where it left off on the last FILEREAD?
No need. Take a look at the file pointer in the file structure. It shows you where you are currently reading from.
-
I see that the FILEREAD command can be called multiple times in sequence. The attached shows the FILEREAD command being used multiple times reading up to 1000 Bytes per use of FILEREAD. This is in a stage and I've gotten it to work. What I would like to do is loop over the FILREAD command multiple times without having individual FILEREAD commands. This would allow a file length of any size (within memory limitations of the BRX) to be read in without knowing it's size before hand. I've tried running this in a for loop but I have been unsuccessful. Can this command be looped over or is there another way to accomplish this?
-
Build the loop in stages. I do it all the time for bulk file or comm transfers.
-
Bob,
Could you give me an example of how you normally implement this. Everything I'm trying is overrunning the memory that I've allocated to read the data into. I'd greatly appreciate it.
-
The attached project worked for me.
-
Thanks Bob. I made a few tweaks to what you provided and it seems to work for my application without issue. Now, another question. Is there a built in command to determine the length of a JSON array? I didn't see one. What I was trying to do is use the JSONPARSE to loop through all elements of a JSON Array without knowing the array's length (using the 0 based array/field option). If there was a command to determine the JSON array length I could loop that many times through the array and extract the elements of the array and write them out to individual memory locations. It looks like I could also use the JSONPARSE command in a while loop and use the JSONPARSE result code to loop until the result code returned a 0 to indicate an element not found. Would this be the easiest approach to doing this, or am I missing an easier way to do this?
-
Use a REPEAT/UNTIL or WHILE loop to iterate the JSONPARSE with an incrementing Array Index, utilizeing the Return Results in a D location (say D99).
In the Help topic for JSONPARSE, it talks about this Return Results D value. The High word will be 0 when the JSON text is good, but your Array Index was not found, e.g. there are only 3 elements in the array, but you passed in a 0-based index of 3. 0, 1, and 2 are valid array indexes in the situation where the record has 3 elements, so when you try to read the 4th (at 0-based index 3), then that tells you you're done.
MOVE 0 V42 // JSON array index, start at 0
REPEAT
JSONPARSE (Lookup by Array Index V42) (Return Result in D99)
STRLE D99:SW1 <= 0 // D99:SW1 is a "cast" which means look at the HIWORD of D99 as a Signed Word, if it's 0 it's done, or < 0 it's in error
OUT C99 // turn on C99 when DONE
STRN C99 // not done?
INC V42 // increment V42 to the NEXT index
UNTIL C99
What's good is that V42 will equal the number of array elements after the UNTIL. So if there are 3 elements in the array, the JSONPARSE will use 0, 1, 2, successfully. When V42 increments to 3 and goes back to the top of the REPEAT, the JSONPARSE will fail when the 0-based index is 3 (i.e. 4th time through the loop), it will set C99, and NOT increment V42 at the bottom of the loop (STRN is a NC contact), hence it will remain equal to 3, the UNTIL will exit the loop since C99 is now ON. And V42 will equal 3 (one beyond the last 0-based index, which is, by definition, the number of items in the JSON array record!)