0

this might be a difficult question, but I'm trying to do the following:

Take an input string i which i want to be a unix timestamp including miliseconds Convert this to an int64 byte array, but i can only do the operations using simpler structures, my largest available int is 32 bit, to expand a bit this is for a PLC to send some telegram to a database

Wanted input:
  "1707461225120" // int64 string 
Should return:
  [00, 00, 01, 8D, 8C, 9E, AA, A0] // 8 byte array

I dont really care what language for responses, i only care about the logical thinking to solve this, anything would be helpful, no advanced data types

I tried the following (want to convert string to int64 8 byte array), sorry if this is a weird language to adhere to, but its all i have, for responses i dont need the same format, i just need the general logic / math, no advanced data types

    byArray : Array[0..31] OF Byte; // temp array of characters in string
    byArrayO : Array[0..7] OF Byte; // temp memory before converting to output
    charCount : Int; // temp amount of characters in input string 16 bit int
    il : Int; // temp counter generic 16 bit int
    i : String; // input string
    o : Array[0..7] OF Byte; // output byte array

    // reset temp memory
    FOR #il := 0 TO 7 DO
        #o[#il] := 0;
        #byArrayO[#il] := 0;
    END_FOR;

    // Convert string to character array
    "STRING_TO_CHARS"(Chars => #byArray,
                      Cnt => #charCount,
                      pChars := 0,
                      Strg := #i); 
    
    // loop character array, here's what im doing wrong, but unsure how to solve this
    FOR #il := 0 TO #charCount - 2 DO // - 2 due to character count offset by 2
        // Function adds an int to a byte array
        "ADD_BYTE_ARRAY"(iAdd := (#byArray[#il] - 48) * 10 ** #il, // convert int char to int and offset
                        arr := #byArrayO); // array to add to
    END_FOR;
    
    #o := #byArrayO;

By this post https://stackoverflow.com/a/28201576/23369035 I need to tweak the add_byte_Array input to keep the memory of the old val value, but how would this be done with a byte array when i cant use int64?

Wanted input:
  "1707461225120"
Should return:
  [00, 00, 01, 8D, 8C, 9E, AA, A0]
What my code does:
   adds the characters in the string together one by one :/
1
  • I thought of a different way to do this entirely, by having the current unix without ms which can fit into a int32, then multiply by 1000 and add the ms, but i need to figure out how to multiply byte[] by int Commented Feb 9, 2024 at 9:34

2 Answers 2

0

I "Solved" my issue by making a way to multiply the byte array by an int32 value then adding the miliseconds

MULT_BYTE_ARRAY

// Multiply to byte array and carry over

#carry := 0;
FOR #i := #LEN TO 0 BY -1 DO
    #sum := BYTE_TO_UDINT(#arr[#i]) * #iMult + #carry;
    #carry := SHR(IN := #sum, N := 8);
    #arr[#i] := UDINT_TO_BYTE(#sum);
END_FOR;
ADD_BYTE_ARRAY

// Add to byte array and carry over

#carry := #iAdd;
FOR #i := #LEN TO 0 BY -1 DO
    #sum := (#arr[#i] & 255) + #carry;
    #arr[#i] := UDINT_TO_BYTE(#sum);
    #carry := SHR(IN := #sum, N := 8);
END_FOR;
"ADD_BYTE_ARRAY"(iAdd := STRING_TO_UDINT(#i), // regular unix timestamp in
                 arr := #byArrayO); 

"MULT_BYTE_ARRAY"(iMult := 1000,
                  arr := #byArrayO);

After this i can add the ms using ADD_BYTE_ARRAY, works fine when you know there wont be any overflow

Sign up to request clarification or add additional context in comments.

Comments

0

Additionally, you can then use the add and mumlt byte arrays to make int64_str_to_bytes

FUNCTION "LINT_STR_TO_BYTES" : Void

VAR_INPUT
  s : String;
END_VAR

VAR_OUTPUT
  bytes : Array[0..#INT64_LEN] OF Byte;
END_VAR

VAR_IN_OUT

END_VAR

VAR_TEMP
  c : Int; // count
  bytesTemp : Array[0..#INT64_LEN] OF Byte;
  strLen : Int;
END_VAR

VAR CONSTANT
  INT64_LEN : Int := 7; // 8 bytes in lint
END_VAR

FOR #c := 0 TO #INT64_LEN DO // clear temp
    #bytesTemp[#c] := 0;
END_FOR;

#strLen := LEN(#s);

FOR #c := 1 TO #strLen DO
    "ADD_BYTE_ARRAY"(arr := #bytesTemp,
                     iAdd := CHAR_TO_BYTE(#s[#c]) - 48);
    IF (#c <> #strLen) THEN
        "MULT_BYTE_ARRAY"(arr := #bytesTemp,
                          iMult := 10);
    END_IF;
END_FOR;

#bytes := #bytesTemp;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.