PDA

Просмотр полной версии : СПК207 и cинхронизация по NTP



vnkorol
15.12.2016, 17:24
Подскажите, вопрос с синхронизацией времени имеет какое-нибудб вменяемое решение?

melky
15.12.2016, 17:37
Был код от capzap для синхронизации с NTP. Не знаю правда, есть ли где в примерах. Поищите.
я на ПЛК100 пробовал, работает.

energvk
15.12.2016, 21:45
Да, я этот код на спк переносил тоже, также работает

vnkorol
16.12.2016, 13:44
Да, я этот код на спк переносил тоже, также работает

Можете поделиться успехом? :)

energvk
16.12.2016, 20:23
Да, чуть позже вечером раскопаю где он у меня - выложу

energvk
16.12.2016, 20:28
Глобальные переменные

VAR_GLOBAL CONSTANT
SOCKET_INVALID :SysTypes.RTS_IEC_HANDLE :=-1; //ошибка открытия порта
END_VAR





FUNCTION SocketCreate : POINTER TO BYTE
VAR_INPUT
in_port :UINT; //порт, с которым нужно установить соединенеие
in_ip :ARRAY [0..3] OF BYTE; //IP адрес
END_VAR
VAR_OUTPUT

END_VAR
VAR_IN_OUT
sock_adr :SOCKADDRESS; //структура, которая содержит всю необходимую информацию для адресации сокета
END_VAR
VAR
openSocket :SysTypes.RTS_IEC_HANDLE; //дескриптор открытого соккета
result :POINTER TO RTS_IEC_RESULT; //указатель на код ошибки системы исполнения (см CmpErrors.library)
err_ok :UDINT :=16#0;
ip_addr :SysSocket.UDINT_IN_BYTES; //ip адрес в формате SysSocket.lib
END_VAR



openSocket:=SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, SOCKET_IPPROTO_IP, result); //открываем соккет (параметры смотреть в библиотеке/GVL)
IF result = err_ok AND openSocket <> SOCKET_INVALID THEN //если нет ошибок, то заполняем структуру SOCKADDRESS
sock_adr.sin_family:=SOCKET_AF_INET; //назначение соккета
ip_addr.s_b1:=in_ip[0]; //формируем ip-адрес
ip_addr.s_b2:=in_ip[1];
ip_addr.s_b3:=in_ip[2];
ip_addr.s_b4:=in_ip[3];
sock_adr.sin_addr.S_un_b := ip_addr;
sock_adr.sin_port:=SysSockHtons(in_port); //указываем порт
IF SysSockConnect(openSocket, ADR(sock_adr), SIZEOF(sock_adr)) < 0 THEN //если соединение с сервером неуспешно
SysSockClose(openSocket); //закрываем соккет
openSocket:=SOCKET_INVALID; //присваиваем ошибку
END_IF;
END_IF;
SocketCreate:=ADR(openSocket^); //выход функции





PROGRAM ntp
VAR
start_bl_ntp :BOOL; //Запуск генератора импульсов
bl_ntp :blink_rst; //Генератор импульсов для работы ntp
start_ntp :BOOL; //Переменная, запускающая ntp-клиент на плк
oldstart_ntp :BOOL; //Предыдущеее значение переменной start_ntp
data_received :BOOL; //Переменная,означающая что данные получены
handle_sock :SysTypes.RTS_IEC_HANDLE;; //Номер открытого сокета
result :__XINT; //Размер полученных данных
ip_address :ARRAY [0..3] OF BYTE := [132,163,4,103]; //IP адрес ntp-сервера (132.163.4.103)
buff_in :ARRAY [0..60] OF BYTE; //Размер принимаемого буфера
sock_adr :SOCKADDRESS;
result_recv :POINTER TO RTS_IEC_RESULT; //указатель на код ошибки системы исполнения (см CmpErrors.library)
str :STRING; //Полученная строка данных с сервера
ntp_true :BOOL; //Полученные данные с сервера - адекватные
t_ntp_man :TOF; //Время ручного получения данных с сервера ntp

hh_ntp :INT;
mm_ntp :INT;
ss_ntp :INT;
dd_ntp :INT;
mh_ntp :INT;
yy_ntp :INT;
set_ntp :BOOL;
END_VAR
VAR CONSTANT
buff_cln : ARRAY [0..60] OF BYTE :=[61(0)]; //Очистка буфера
END_VAR





(*****Отдельная благодарность capsar`у за ntp-клиент*****)
IF vis_bright_time.current_time>10800 AND vis_bright_time.current_time<10980 AND gprs_online THEN (*Если текущее время 03:00 выполняем 6 попыток опроса сервера и есть связь с интернетом, либо вручную с панели, при наличии интернета*)
start_bl_ntp:=TRUE;
ELSE
start_bl_ntp:=FALSE;
END_IF

bl_ntp(in:=start_bl_ntp , t_on:= T#5S, t_off:= T#25S, out=> ); //генератор импусьсов, который в течении работы таймера отправляет на панель данные
t_ntp_man(IN:= ntp_man, PT:= T#5S, Q=> , ET=> ); //время опроса ntp-сервера при ручном опросе

IF (bl_ntp.out OR t_ntp_man.Q) AND ntp_yes THEN //если подошло время обновления или синхр. вручную при условии разрешения синхронизации
start_ntp:=TRUE; //запускаем ntp-клиент
IF start_ntp AND start_ntp<>oldstart_ntp THEN //сравнение с передыдущим значением переменной
handle_sock := SocketCreate(13,ip_address, sock_adr); //работа через соккет и получение данных от сервера
data_received:=FALSE;
buff_in:=buff_cln;
ELSIF oldstart_ntp AND start_ntp<>oldstart_ntp THEN
IF handle_sock<>SOCKET_INVALID THEN
SysSockClose(handle_sock);
handle_sock := SOCKET_INVALID;
END_IF
ELSIF start_ntp THEN
IF NOT data_received THEN
result:=SysSockRecv(handle_sock, ADR(buff_in[0]), SIZEOF(buff_in),0,result_recv);
IF result > 0 THEN //если результат > 0, т.е. положителен*)
str:=bytePackStr(ADR(buff_in[0]), __XINT_TO_DINT (result)); //формируется строка данных из буфера*)
data_received:=TRUE; //формирование строки завершено*)
ntp_true:=INT_TO_BOOL (FIND(str,'UTC')); //проверка,что строка не состоит из неопределенных символов (время от времени бывает)
IF ntp_true THEN //соответственно, если данные адекватные - обрабатываем их
hh_ntp:=STRING_TO_INT (MID(str,2,17))+gmt; //получаем значение часа - 18-19 символы и приводим к часовому поясу
mm_ntp:=STRING_TO_INT (MID(str,2,20)); //См. hh_ntp
ss_ntp:=STRING_TO_INT (MID(str,2,23)); //См. hh_ntp
yy_ntp:=STRING_TO_INT (MID(str,2,8)); //См. hh_ntp
mh_ntp:=STRING_TO_INT (MID(str,2,11)); //См. hh_ntp
dd_ntp:=STRING_TO_INT (MID(str,2,14)); //См. hh_ntp
set_ntp:=TRUE; //фронт для установки полученного времени в плк
END_IF
END_IF
END_IF
END_IF
ELSE
start_ntp:=FALSE;
ntp_true:=FALSE;
set_ntp:=FALSE;
END_IF
oldstart_ntp:=start_ntp; (*Присваиваем промежуточную переменную*)

vnkorol
21.12.2016, 16:41
Большое спасибо! буду пробовать! А вызов как организован? С каким интервалом?

energvk
22.12.2016, 01:16
Большое спасибо! буду пробовать! А вызов как организован? С каким интервалом?



IF vis_bright_time.current_time>10800 AND vis_bright_time.current_time<10980 AND gprs_online THEN (*Если текущее время 03:00 выполняем 6 попыток опроса сервера и есть связь с интернетом, либо вручную с панели, при наличии интернета*)


Т.е. раз в сутки либо вручную

vnkorol
28.12.2016, 10:17
Продолжим тему. С получением по NTP времени разобрались. Подскажите самый простой способ записи полученных значений даты и времени в системные часы, пожалуйста.

PavelGO
19.04.2018, 12:28
Ловчее всего ntpdate было бы использовать, но в linux спк 207 ntp к сожалению нет.