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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.