NTP?
NTP is the Network Time Protocol, a communication protocol for synchronizing devices on a network with the correct time. It is the most basic of all protocols.
Flow
There are NTP Server and Client, and it assumes that the NTP Server provides the correct time to the NTP client. The flow is that the NTP Server waits for a request from the NTP Client, and when a request for time synchronization comes in, it gives the current time.
NTP Protocol
The Format of the NTP protocol is as follows. The length is 48, the first is the basic settings such as Version, Mode, Delay, etc. The time returned by the NTP server is 32~39 bytes is the B time and 40~47 bytes is the C time.
Learn more about the protocol from here:
https://tools.ietf.org/html/rfc4330
Implementation
Let us first introduce the usage and implementation of the Siemens NTP library, and then look at the contents of the library.
Download
Access the following Link.
V15.1 is used in this tutorial, please download the TIAV15.1 Zip and PDF documents.
Installation
First, unzip the ZIP.
Go to Global libraries>Open Library and select and open LSNTP.al15_1 in the folder you unzipped earlier.
Insert the LSNP_Server and LSNP_Param into your program.
Configuration
Since I don’t have the real hardware, I will test it with SimAdv and LinuxOS with python and NTP Client.
Program
Just call LSNTP_Server and assign hwID to Local~PROFINET_interface, then initialize by turning on the init input.
テストTest
ntplib is used in this tutorial:
https://pypi.org/project/ntplib/
Code
>>> import ntplib >>> from time import ctime >>> c = ntplib.NTPClient() >>> host=’192.168.11.50′ >>> response = c.request(host, version=3) >>> response.offset >>> response.version >>> ctime(response.tx_time) |
Inside the library..
Flow
The library waits for a request as following flow: first initialize > disconnect > connect > check if a request is received > if so, check if the data is of length 48 > send > finish sending > wait for a request.
This is the Flow where the error occurs.
statSend.tel
The details of the connection creation are similar, so I won’t go into detail here. What we want to explain is how to set up the NTP protocol. statSend.tel is used to send the message to the NTP Client.
First, let’s look at flags.
flags[0]
From Line181. the MODE_SERVER is constant and contains 2#00011100, the Siemens library is a constant for the most part with All capitalized variables.
So what is 2#00011100?
#statSend.tel.flags[0] := #MODE_SERVER; // Mode – No Warning, NTP Version 3, Server |
As Comment also wrote, No Warning,NTP Version 3,Server Mode.
flags[2]
The logarithm of log2 to the maximum time interval (in seconds) before the next NTP packet is sent. For example, 10 means 2 ** 10 squared = 1024 seconds.
#statSend.tel.flags[2] := #statRcv.tel.flags[2]; //Poll – Peer polling intervall copied from request |
flags[3]
Stores the precision with which the system clock can be used by devices handling NTP.In Comment,Clock Precision -6 = -0,015625s (for S7-1200), but the source is unknown.
#statSend.tel.flags[3] := #CLOCK_PRECISION; |
rootDelay
To be honest, I’m not sure, so I’ll leave it at 0.
#statSend.tel.rootDelay := 0; // Root Delay |
rootDispersion
This is also not clear.
#statSend.tel.rootDispersion := 0; // Root Dispersion |
referenceId
What NTP Server devices the Client is synchronizing.
//Set reference identifier according to RFC 4330, only LOCL, DCF and GPS used CASE #referenceId OF 1: Strg_TO_Chars(Strg := ‘DCF$00’, Cnt => #tempNumChar, Chars := #statSend.tel.referenceId, pChars := 0); 2: Strg_TO_Chars(Strg := ‘GPS$00’, Cnt => #tempNumChar, Chars := #statSend.tel.referenceId, pChars := 0); ELSE Strg_TO_Chars(Strg := ‘LOCL’, Cnt => #tempNumChar, Chars := #statSend.tel.referenceId, pChars := 0); END_CASE; |
timestamps.receive.sec
The time when you last received an NTP packet from the other party. It is used for time synchronization calculations.
Various conversions are performed. Let’s break it down in detail,
The last 1 + 2 + DELTA_1900_1970 + DELTA_1970_1990 is the number of seconds of the current time, assuming the NTP timestamps are in UTC (Coordinated Universal Time), 1900/1/1 0:00:00 is used as the starting point (=0).
// Convert System Time (UTC) to NTP Time #statSend.tel.timestamps.receive.sec := (DATE_TO_UDINT(DTL_TO_DATE(#tempSysTime)) * #SEC_PER_DAY) + (TOD_TO_UDINT(DTL_TO_TOD(#tempSysTime)) / 1000) + #DELTA_1970_1990 + #DELTA_1900_1970; |
statSend.tel.timestamps.receive.secFra
。The lower 32 bits are decimal points.
#statSend.tel.timestamps.receive.secFrac := LREAL_TO_UDINT(UDINT_TO_LREAL(#tempSysTime.NANOSECOND) * 2 ** 32 / 10 ** 9); |
WireShark
I won’t explain ALL here because the Time Frames are all the same.Let’s look at the last one in Wireshark.How would this Time stamp be converted?
As a carve-out:
The answer is 3828487166,.
This shows the number of seconds since January 1, 1900, 0:0:0. This will be converted to hours, minutes, and seconds.
The day is,
3828487166/86400=44311.194
The remaining seconds are: 3828487166%44311.194=16766
The time is: 16766/3600=4.567,From WireShark’s point of view, well, it is 4 hours.
The remaining seconds are:16,766%3600=2366
The minutes are: 2366/60=39.43. Well, this is a rough calculation, so 38 minutes is correct.
Calculate it like this.