Как получить метку времени Unix в TwinCAT3?

Мы работаем над приложением регистрации данных в Beckhoff TwinCAT3. Чтобы получить время, которое мы в настоящее время используем LTIME(), затем преобразуем его в C# в ms, используя:

ulong valA = reader.ReadUInt64();   // this gets the LTIME
long ftime = (long)(valA / 100);
DateTime t = DateTime.FromFileTime(ftime);
return (t.ToUniversalTime().Ticks - 621355968000000000) / 10000;

Должен быть лучший способ. Кроме того, мы видим разницу между этим временем и временем компьютера (на панели задач).

Какой лучший способ получить мс с 1970 (по Гринвичу) с компьютерных часов?

Я вижу NT_GetTime. Похоже, что тогда мы должны были бы сделать математику на структуре

Спасибо за любые указатели.

1 ответ

Ключом к этому является использование FB_TzSpecificLocalTimeToFileTime для преобразования текущего T_FILETIME в UTC с использованием информации о текущем часовом поясе ( ST_TimeZoneInformation). Это будет время файла UTC для окон (отметки), которое должно быть привязано ко времени UTC Unix.

Вот реализация функционального блока этого процесса:

декларация

FUNCTION_BLOCK UnixTimestamp
VAR_OUTPUT
    seconds: ULINT;
    milliseconds: ULINT;
END_VAR

VAR
    localSystemTime : FB_LocalSystemTime := ( bEnable := TRUE, dwCycle := 1 );
    getTimeZoneInformation : FB_GetTimeZoneInformation;
    timeZoneInformation : ST_TimeZoneInformation;
    specificLocalTimeToFileTime : FB_TzSpecificLocalTimeToFileTime;
    fileTime: T_FILETIME;
    onZerothSecondLastCycle : BOOL;
END_VAR

Реализация

// Get local system time
localSystemTime();

// On the zeroth second of each minutesync timezone information
IF (timeZoneInformation.standardName = '' OR (localSystemTime.systemTime.wSecond = 0 AND NOT onZerothSecondLastCycle)) THEN
    getTimeZoneInformation(sNetID := '', bExecute := TRUE, tzInfo => timeZoneInformation);
END_IF;

// Convert local system time to unix timestamps
specificLocalTimeToFileTime(in := Tc2_Utilities.SYSTEMTIME_TO_FILETIME(localSystemTime.systemTime), tzInfo := timeZoneInformation, out => fileTime);
seconds := (SHL(DWORD_TO_ULINT(fileTime.dwHighDateTime), 32) + DWORD_TO_ULINT(fileTime.dwLowDateTime)) / 10000000 - 11644473600;
milliseconds := (SHL(DWORD_TO_ULINT(fileTime.dwHighDateTime), 32) + DWORD_TO_ULINT(fileTime.dwLowDateTime)) / 10000 - 11644473600000;

onZerothSecondLastCycle := localSystemTime.systemTime.wSecond = 0;

использование

VAR
    unixTime: UnixTimestamp;
    timestampSeconds: ULINT;
    timestampMilliseconds: ULINT;
END_VAR

-----

unixTime();
timestampMilliseconds := unixTime.milliseconds;
timestampSeconds := unixTime.seconds;
Другие вопросы по тегам