=====PC Engines APU1 - Hopf NTP Server===== ====Requirements==== * PC Enginges board, with DCD line (APU = ok, ALIX = not ok) * Debian 10 installed. * Getty on ttyS0 disabled. * APU1 to Hopf 7001 system connected over serial (see wiring below). * Hopf 7245 interface card configured for NTP (see 7245 interface board documentation). * [[http://www.ntp.org/downloads.html|NTP source code]] download. ====Documentation==== * [[https://www.hopf.com/documents_en.php|Hopf documentation]] * {{ ::7001-7015dcf77_v0801_en.pdf |Hopf 7001DCF77 system}} * {{ ::7245_v0600_en.pdf |Hopf 7245 interface board}} * {{ :apu1.pdf |PC Engines APU1 board}} * Interface board 7245 DIP-switch settings. 1 = on 0 = off SW1 SW2 SW3 12345678 12345678 12345678 11111001 11000111 11111110 ====Serial cable==== * Construct a serial cable to route PPS to DCD. Hopf 7245 1 GND --------- 5 GND PC Engines S1 RS232 2 TXD --------- 2 RXD APU1 board 6 RTS (PPS) --- 1 DCD ====Install packages==== * Install required tooling. apt install build-essential libcap-dev pps-tools ====Create device symlinks and PPS device==== * Create new udev rules file. cat > /etc/udev/rules.d/hopf.rules < * Reload the udev rules or reboot to test. ls -l /dev/refc* lrwxrwxrwx 1 root root 5 Jan 4 14:37 /dev/refclock-0 -> ttyS0 lrwxrwxrwx 1 root root 4 Jan 4 14:37 /dev/refclockpps-0 -> pps0 ppstest /dev/pps0 trying PPS source "/dev/pps0" found PPS source "/dev/pps0" ok, found 1 source(s), now start fetching data... source 0 - assert 1578145727.901770116, sequence: 1313 - clear 1578145072.692767609, sequence: 2 source 0 - assert 1578145728.000351551, sequence: 1314 - clear 1578145072.692767609, sequence: 2 source 0 - assert 1578145728.901731373, sequence: 1315 - clear 1578145072.692767609, sequence: 2 source 0 - assert 1578145729.000557999, sequence: 1316 - clear 1578145072.692767609, sequence: 2 ^C ====Install NTP==== * Disable and remove other time sync applications. apt-get remove --purge ntp chrony timedatectl set-ntp false systemctl stop systemd-timesyncd systemctl disable systemd-timesyncd * Add ntp user. groupadd ntp useradd -c "Network Time Protocol" -d /var/lib/ntp -g ntp -s /bin/false ntp usermod -a -G dialout ntp * Create directories. install -v -o ntp -g ntp -d /var/lib/ntp install -v -o ntp -g ntp -d /var/log/ntpstats * Compile source code. tar zxf ntp-4.2.8p13.tar.gz cd ntp-4.2.8p13 # from Linux From Scratch ./configure CFLAGS="-O2 -g -fPIC" \ --prefix=/usr \ --bindir=/usr/sbin \ --sysconfdir=/etc \ --enable-linuxcaps \ --enable-parse-clocks \ --with-lineeditlibs=readline \ --docdir=/usr/share/doc/ntp-4.2.8p13 make make install * Add systemd services. cat > /etc/systemd/system/ntpd.service < /etc/systemd/system/pps.server < ====Hopf DCF /etc/ntp.conf==== * Create /etc/ntpd.conf. #Stratum level when no ref source available tos orphan 12 # Hopf DCF clock # Mode 12 + 128 (pps) = 140 server 127.127.8.0 mode 140 fudge 127.127.8.0 refid PPS # Reference identifier #leapfile /etc/leap_second restrict -4 default notrap nomodify nopeer noquery restrict -6 default notrap nomodify nopeer noquery restrict 127.0.0.1 restrict ::1 statsdir /var/log/ntpstats/ statistics loopstats peerstats clockstats filegen loopstats file loopstats type day enable filegen peerstats file peerstats type day enable filegen clockstats file clockstats type day enable driftfile /var/lib/ntp/ntp.drift ====Check timecode==== ntpq -c 'cv 0 timecode' timecode="\x02CB154556010120\x0a\x0d\x03" ====Nagios Hopf 7001 check==== #!/bin/bash # # Tested with Hopf 7001 DCF Base station with 7245 serial interface boards # Datastring 7001/6021 # # BS, 2013/05 ntpq="/usr/bin/ntpq" # get timecode variable, received from the clock eval `$ntpq -c 'cv 0 timecode'` function quit { case "$2" in 0) echo "OK: $1" exit 0 ;; 1) echo "Warning: $1" exit 1 ;; 2) echo "Critical: $1" exit 2 ;; 3) echo "Unknown: $1" exit 3 ;; esac } function clockstat { # Status nibble from hex hex0=0000 hex1=0001 hex2=0010 hex3=0011 hex4=0100 hex5=0101 hex6=0110 hex7=0111 hex8=1000 hex9=1001 hexA=1010 hexB=1011 hexC=1100 hexD=1101 hexE=1110 hexF=1111 eval statnibble='hex$1' snibble=${!statnibble} case ${snibble:0:2} in 00) textstatus="time/date invalid" exitcode=2 ;; 01) textstatus="crystal operation" exitcode=1 ;; 10) textstatus="radio operation" exitcode=0 ;; 11) textstatus="radio operation (high accuracy)" exitcode=0 ;; esac case ${snibble:2:1} in 0) dss="standard time" ;; 1) dss="daylight saving time" ;; esac case ${snibble:3:1} in 0) ann="no announcement hour" ;; 1) ann="announcement (ds-st-ds)" ;; esac quit "status hex=\"$1\", bin=\"$snibble\": $textstatus, $dss, $ann" $exitcode } # check for complete string, for example: \x028D194223310513\x0a\x0d\x03 # This is from the Hopf 7245 serial interface board # # x20 = Space # x0D = CR (carriage return) # x0A = LF (line feed) # x02 = STX (start of text) # x03 = ETX (end of text) # if [[ $timecode == \\x02*\\x0a\\x0d\\x03 ]]; then clockstat ${timecode:4:1} else quit "Timecode not complete" 3 # return Unkown status fi =====Troubleshooting===== * Show peer status: ntpq -p * Show timecode from receiver: ntpq -c 'cv 0 timecode' * Show client list (max. 600): ntpdc -n -c monlist ## ntp 2.4.7 removed monlist in favour of ntpq's mrulist ntpq -c "mrulist" {{tag>[hardware alix ntp]}}