1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | FUNCTION_BLOCK JSON_TO_STRUCT VAR_INPUT Execute: BOOL; //rising edge triggers parse of JSON string Abort: BOOL; //rising edge stops parsing of JSON string JSONVars: POINTER TO ARRAY[1..GPL_JSON.MAX_VARS] OF JSONVAR; //pointer to local structure made up of type JSONVAR NumberOfVars: UINT; //number of variables in the local structure or array VAR_OUTPUT Aborted: BOOL; //parsing aborted by Abort input Error: BOOL; //unexpected character detected, string not completely parsed ErrorPosition: UDINT; //character position where the unexpected character was found VAR obj_level: UINT; //number of nested objects name_stop: UDINT; //index of the end of a name value_stop: UDINT; //index of the end of a value i: UDINT; //loop indexes levelindex: UINT; parse JSON string and place the values in a matching local structure of type JSONVAR thisloopstarttime:= TIME(); //store the time of the beginning of this loop Execute_TRIG(CLK:= Execute); Abort_TRIG(CLK:= Abort); IF Execute_TRIG.Q THEN //must see a rising edge on execute to start parsing //parse the input string, and start storing values in NameValue array WHILE parse DO //there might not always be a null character, for example in a network buffer that is stored as an array of bytes parse:= FALSE; Done:= TRUE; Busy:= FALSE; ParseTime:= TIME() - starttime; RETURN; END_IF CASE JSONString^[bufferposition] OF ASCII.DOUBLE_QUOTE: // " name string Name(); ASCII.OPEN_BRACE:// {, beginning of object OpenObject(); ASCII.CLOSE_BRACE:// }, end of object CloseObject(); ASCII.OPEN_BRACKET: // [, beginning of array OpenArray(); ASCII.CLOSE_BRACKET: // ], end of array CloseArray(); ASCII.COLON: // :, separator for name:value pairs Value(); ASCII.COMMA: // , move to next object Comma(); (*========================================LOOK FOR NAMES IN LOCAL VARIABLES========================================*) IF findname THEN (*loop through all configured objects and look for the name that is currently being worked on in the JSON string This function will eventually find all objects, but it will start looking after the previous found variable, as it //Match name and array index. Array index will be 0 if the current name:value is not part of an array foundname:= TRUE; //name in JSON string matches the local variable name ELSE (*====================FOUND NAME, WRITE LOCAL VAR====================*) IF foundname THEN //local var name matches with JSON string name foundname:= FALSE; IF TIME() >= (thisloopstarttime + GPL_JSON.MAX_EXECUTION_TIME) THEN //very long strings or files could take too long to parse in one task cycle, and cause a watchdog exception END_WHILE |