Всё верно, ведь это несовместимые типы. Чтобы понять, нужно разобраться с типами данных и с тем, как в них хранятся данные.
TIME_OF_DAY - беззнаковое 32-битное целое (описание здесь (http://www.plccenter.cn/Siemens_Step7/IDH_TIME_OF_DAY_Data_Type.htm)), в скаде ему соответствует тип данных LongWord, но никак не DateTime.
DateTime - вещественное, двойной точности, 64 бита, он равен типу данных Double и является им по сути (описание здесь (http://www.delphibasics.ru/TDateTime.php)).
Как мы писали ранее, несовместимые типы придется преобразовывать, т.к. данные в них хранятся по-разному. Количество миллисекунд (т.е. TIME_OF_DAY) можно легко перевести в тип DateTime, по формуле:
begin
vrDateTime.Value := vrTOD.AsInt64 / 86400000;
end.
скрипт должен выполняться по изменению переменной vrTOD. Тогда при vrTOD = 1000, в переменной DateTime время будет равно одной секунде 00:00:01.000.
и через календарь имеем часы и минуты. А всё же нужно ещё дни.
Через календарь невозможно вывести значения времени, без привязки к году и месяцу. Он не предназначен для вывода времени таймеров (счетчиков секунд/миллисекунд). Это самый обычный Календарь, а не секундомер.
Если Вам нужно отобразить таймер наработки на мнемосхеме, то просто разместите на мнемосхеме компонент Текст, привяжите его к переменной Time (0..4294967295) и на событие OnDataChange назначьте следующий скрипт:
var
v: Int64;
days, hours, minutes, seconds, msc: Integer;
function AddZeros(AValue, ALen: Integer): string;
begin
Result := IntToStr(AValue);
while Length(Result) < aLen do
Result := '0' + Result;
end;
begin
if Sender is TM_Text then
with Sender as TM_Text do
begin
v := AsInt64;
days := v div 86400000;
hours := (v div 3600000) mod 24;
minutes := (v div 60000) mod 60;
seconds := (v div 1000) mod 60;
msc := v mod 1000;
Text := AddZeros(days, 2) + ' дней ' + AddZeros(hours, 2) + ':' + AddZeros(minutes, 2) + ':' + AddZeros(seconds, 2) + '.' + AddZeros(msc, 3);
end
end.
Это универсальный скрипт, его можно назначить множеству компонентов Текст и в них будет отображаться время в формате 00 дней 00:00:00.000 взятое из связанной переменной.
Товарищи разработчики, сжальтесь, нужна нативная поддержка типа TOD.
Wildrover, если Вам также нужно только отобразить значение времени наработки из переменной TOD на мнемосхеме, то нет необходимости делать отдельные переменные TDateTime, Вы также можете использовать всего один универсальный скрипт и любое количество компонентов Текст, как описано выше. TOD - это обычная LongWord переменная, отобразить её значение в скаде, при необходимости, можно как угодно.
Wildrover, если Вам также нужно только отобразить значение времени наработки из переменной TOD на мнемосхеме, то нет необходимости делать отдельные переменные TDateTime, Вы также можете использовать всего один универсальный скрипт и любое количество компонентов Текст, как описано выше. TOD - это обычная LongWord переменная, отобразить её значение в скаде, при необходимости, можно как угодно.
Нет. Задача совершенно другая.
Имеем 320 групп освещения, у каждой есть время включения и отключения.
Получается что нам надо отконвертить 640 переменных из LongWord (так TOD приходит в скаду) в DateTime (все эти переменные еще нужно вручную завести), а потом обратно.
Зачем коллега использует TOD для наработки, спросите у него. Если дни его не интересуют или он их отсчитывает в отдельной переменной, это его дело.
Мне нужно именно время дня для включения и отключения систем, с возможностью редактирования в скаде.
Так как программы для контроллеров так же пишу я, то есть возможность сделать следуещее в Codesys:
VAR RETAIN
StartStop: WORD;
StartTime: LREAL;
StopTime: LREAL;
END_VAR
(https://i.ibb.co/NVWyrLz/start.png)
Тогда переменные StartTime и StopTime, после импорта в Simple-Scada объявляем не Double, а DateTime и можно их использовать в объекте TMCalendar.
Пока так. Но тем не менее хотелось бы иметь нативную поддержку TOD.
Здравствуйте.
У меня таких таймеров 30шт и надо сохранить в файл. Создавать 30 переменных и 30 скриптов?
См. комментарий к скрипту:
Это универсальный скрипт (https://simple-scada.com/help/script/script-types.html), его можно назначить множеству компонентов Текст и в них будет отображаться время в формате 00 дней 00:00:00.000 взятое из связанной переменной.
Соответственно, писать 30 отдельных скриптов не требуется. Если полученное значение нужно записывать в строковую переменную, то эту переменную можно указать в свойство "Доп. переменная" компонента "Текст" и в скрипт добавить запись в доп. переменную:
var
v: Int64;
s: String;
days, hours, minutes, seconds, msc: Integer;
begin
if Sender is TM_Text then
with Sender as TM_Text do
begin
v := AsInt64;
days := v div 86400000;
hours := (v div 3600000) mod 24;
minutes := (v div 60000) mod 60;
seconds := (v div 1000) mod 60;
msc := v mod 1000;
s := ZeroPad(days, 2) + ' дней ' + ZeroPad(hours, 2) + ':' + ZeroPad(minutes, 2) + ':' + ZeroPad(seconds, 2) + '.' + ZeroPad(msc, 3);
VariableEx.Value := s; // записываем полученную строку в доп. переменную
Text := s; // выводим полученную строку в компонент "Текст"
end
end.
Если наработку нужно записывать в строковые переменные и не требуется выводить на мнемосхему, то можно использовать скрипт с типом события "Изменились переменные (https://simple-scada.com/help/script/changed-the-variables.html)" указав все 30 переменных в список скрипта и изменив код скрипта под используемый тип события. Например переменные таймеров (с OPC-сервера) имеют имена: vrMyTimer1 … vrMyTimer30. Тогда нужно создать внутренние строковые переменные с именами: vrMyTimer1_String … vrMyTimer30_String и использовать следующий код скрипта:
var
v: Int64;
aVar: TM_Variable;
days, hours, minutes, seconds, msc: Integer;
begin
aVar := GetVariableByName(Variable.Name + '_String');
if aVar <> nil then // если переменная существует
begin
v := Variable.AsInt64;
days := v div 86400000;
hours := (v div 3600000) mod 24;
minutes := (v div 60000) mod 60;
seconds := (v div 1000) mod 60;
msc := v mod 1000;
// записываем полученную строку в переменную vrMyTimer#_String
aVar.Value := ZeroPad(days, 2) + ' дней ' + ZeroPad(hours, 2) + ':' + ZeroPad(minutes, 2) + ':' + ZeroPad(seconds, 2) + '.' + ZeroPad(msc, 3);
end;
end.