<< Click to Display Table of Contents >> Navigation: Работа в режиме исполнения > Работа со средой исполнения > Синхронизация времени узла |
В MasterSCADA 4D можно реализовать синхронизацию узлов проекта по времени с использованием скрипта C# и ФБ SetDateAndTime.
Рассмотрим пример создания проекта, в котором будут реализованы: запрос времени по NTP c сервера времени и установка запрошенного времени в локальный узел.
1. Создадим проект в среде разработки MasterSCADA 4D. В дерево системы добавим узел АРМ. Настройки узла оставим по умолчанию:
2. Чтобы запросить время по протоколу NTP с сервера времени, нужно написать скрипт на языке C#. Для этого в проект добавим объект и программу C#:
3. В программу добавим два параметра:
•pRun - входной параметр типа Bool;
•Параметр_1 - выходной параметр типа DT.
4. В редакторе C# запишем следующий скрипт:
Скриншот скрипта |
Текст скрипта |
public sealed class Program : ScriptBase { public sealed class Program : ScriptBase { public override void Execute() { if (pRun) { Параметр_1 = GetNetworkTime(); } } public static DateTime GetNetworkTime() { //const string NtpServer = "pool.ntp.org"; const string NtpServer = "ntp0.ntp-servers.net"; /* https://www.ntp-servers.net/servers.html Ярус Адрес сервера IPv6 Состояние Нагрузка 1 ntp0.ntp-servers.net Есть Работает Средняя 1 ntp1.ntp-servers.net Нет Работает Высокая 1 ntp2.ntp-servers.net Есть Работает Высокая 1 ntp3.ntp-servers.net Есть Работает Средняя 2 ntp4.ntp-servers.net Есть Работает Низкая 2 ntp5.ntp-servers.net Нет Работает Низкая 2 ntp6.ntp-servers.net Есть Работает Низкая 2 ntp7.ntp-servers.net Нет Работает Низкая */ const int DaysTo1900 = 1900 * 365 + 95; // 95 = offset for leap-years etc. const long TicksPerSecond = 10000000L; const long TicksPerDay = 24 * 60 * 60 * TicksPerSecond; const long TicksTo1900 = DaysTo1900 * TicksPerDay; var ntpData = new byte[48]; ntpData[0] = 0x1B; // LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode) var addresses = Dns.GetHostEntry(NtpServer).AddressList; var ipEndPoint = new IPEndPoint(addresses[0], 123); long pingDuration = Stopwatch.GetTimestamp(); // temp access (JIT-Compiler need some time at first call) using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { socket.Connect(ipEndPoint); socket.ReceiveTimeout = 5000; socket.Send(ntpData); pingDuration = Stopwatch.GetTimestamp(); // after Send-Method to reduce WinSocket API-Call time
socket.Receive(ntpData); pingDuration = Stopwatch.GetTimestamp() - pingDuration; } long pingTicks = pingDuration * TicksPerSecond / Stopwatch.Frequency; // optional: display response-time // Console.WriteLine("{0:N2} ms", new TimeSpan(pingTicks).TotalMilliseconds); long intPart = (long)ntpData[40] << 24 | (long)ntpData[41] << 16 | (long)ntpData[42] << 8 | ntpData[43]; long fractPart = (long)ntpData[44] << 24 | (long)ntpData[45] << 16 | (long)ntpData[46] << 8 | ntpData[47]; long netTicks = intPart * TicksPerSecond + (fractPart * TicksPerSecond >> 32); var networkDateTime = new DateTime(TicksTo1900 + netTicks + pingTicks / 2); return networkDateTime.ToLocalTime(); // without ToLocalTime() = faster } } } |
Если параметр программы pRun будет равен TRUE, то Параметр_1 будет равен результату вызова метода GetNetworkTime(), т.е. времени сервера.
5. Добавим параметр ВремяСервера типа DT в дерево объектов и свяжем его с выходным параметром программы, перетащив параметр программы на параметр объекта:
6. Чтобы в режиме исполнения была возможность синхронизировать время узла с временем сервера, добавим в объект программу FBD. В редактор из палитры элементов добавим ФБ SetDateAndTime:
7. В программу FBD добавим 3 параметра:
•Время сервера - входной параметр. Создадим его, перетащив одноименный параметр с дерева на клеммник входа;
•Установить - входной параметр типа Bool;
•ErrorCode - выходной параметр. Создадим его, перетащив одноименный выход ФБ на клеммник выхода.
Далее свяжем параметр Установить со входом ФБ Execute, а параметр Время сервера - со входом DataAndTime:
8. Перейдем в режим исполнения проекта. По умолчанию Параметр_1 программы C# передает время: 0001-01-01-00:00, а параметр pRun равен False:
При изменении значения параметра pRun на True, будет вызван метод программы GetNetworkTime() и время сервера передастся в ФБ SetDateAndTime, который будет устанавливать получаемые дату и время в системное время узла. Если изменить значение параметра программы FBD Установить, то изменение системного времени будет происходить по переднему фронту изменения значения данного входа.
Смотрите также: