Problem bei Projektarbeit

Marco

Neues Mitglied
Hallo, ich arbeite derzeit an einer Projektarbeit in der ich meine PC-Uhr mit GPS auf mindestens 10ms genau synchronisieren soll.

Ich weiß nicht ob das Forum für solche Fragen der richtige Platz ist, aber ich komme nicht wirklich weiter. Sollte dieses Forum der falsche Ort sein, vielleicht hat da jemand einen Tipp für mich.

Nun bin ich zwar Elektrotechnikstudent aber meine Programmierkenntnisse halten sich trotzdem in Grenzen.
Daher bin ich in noch nicht sehr weit gekommen. ( Kenntnisse nur in C vorhanden)

Ich habe durch Hinweise von meinem Professor einen Programmcode gefunden ( in C) der die Nachrichten des GPS Empfängers in eine Textdatei schreibt. Diese habe ich bereits dahingehend erweitert dass nur die gnrmc Nachrichten (die Nachricht die die Uhrzeit enthällt) in diese Textdatei geschrieben werden.

Nun stehe ich aber vor folgenden Problemen:
-ich soll beweisen, dass die Abweichung vom GPS zu einem NTP Server nicht steigt. Dafür soll ich Code finden der einen NTP Aufruf stellt und ich dadurch die Zeit des NTP Servers quasi gleichzeitig zur GPS Zeit abfrägt , so dass ich diese vergleichen kann
-ich muss ja auf kurz oder lang die Systemzeit mit dem c-Code setzen, habe da auch evtl. Ansätze gesehen aber verstehe diese nicht so ganz bzw. sind schwer für mich nachzuvollziehen

-laut meinem Professor braucht das Programm für das Setzen der Systemzeit Adminrechte,habe daraufhin gegoogelt, bin dort aber auch nicht wirklich weiter gekommen.

Vielleicht kann mir von euch jemand zumindest bei einem Problem weiterhelfen oder hat Tipps.
Vielen Dank fürs lesen im Voraus

Mit freundlichen Grüßen

Marco
 
ich soll beweisen, dass die Abweichung vom GPS zu einem NTP Server nicht steigt. Dafür soll ich Code finden der einen NTP Aufruf stellt und ich dadurch die Zeit des NTP Servers quasi gleichzeitig zur GPS Zeit abfrägt , so dass ich diese vergleichen kann

"Code finden" klingt so, als wären Librarys erlaubt. Suche mal eine NTP-Library für C (damit du die Pakete nicht selbst bauen musst, die du vom Dienst empfängst).


-laut meinem Professor braucht das Programm für das Setzen der Systemzeit Adminrechte,habe daraufhin gegoogelt, bin dort aber auch nicht wirklich weiter gekommen.

Ich nehme mal an, das soll unter Linux laufen?

Möglichkeit 1: mit sudo aufrufen oder als root
Möglichkeit 2: setuid flag in der Binärdatei und ein Admin als Besitzer (Vorsicht)
 
Ich las was von NTP... vllt hilf es ja

ntp.c:
#include "ntp.h"
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

void error(char *msg) {
  perror(msg); // Print the error message to stderr.
  exit(0);     // Quit the process.
}

time_t GetNtpTime(void) {

  int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket.

  int portno = 123; // NTP UDP port number.

  char *host_name = "de.pool.ntp.org"; // NTP server host-name.

  // Structure that defines the 48 byte NTP packet protocol.

  typedef struct {

    uint8_t li_vn_mode; // Eight bits. li, vn, and mode.
                        // li.   Two bits.   Leap indicator.
                        // vn.   Three bits. Version number of the protocol.
                        // mode. Three bits. Client will pick mode 3 for client.

    uint8_t stratum;   // Eight bits. Stratum level of the local clock.
    uint8_t poll;      // Eight bits. Maximum interval between successive messages.
    uint8_t precision; // Eight bits. Precision of the local clock.

    uint32_t rootDelay;      // 32 bits. Total round trip delay time.
    uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source.
    uint32_t refId;          // 32 bits. Reference clock identifier.

    uint32_t refTm_s; // 32 bits. Reference time-stamp seconds.
    uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second.

    uint32_t origTm_s; // 32 bits. Originate time-stamp seconds.
    uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second.

    uint32_t rxTm_s; // 32 bits. Received time-stamp seconds.
    uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second.

    uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
    uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second.

  } ntp_packet; // Total: 384 bits or 48 bytes.

  // Create and zero out the packet. All 48 bytes worth.

  ntp_packet packet = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

  memset(&packet, 0, sizeof(ntp_packet));

  // Set the first byte's bits to 00,011,011 for li = 0, vn = 3, and mode = 3. The rest will be left set to zero.

  *((char *)&packet + 0) = 0x1b; // Represents 27 in base 10 or 00011011 in base 2.

  // Create a UDP socket, convert the host-name to an IP address, set the port number,
  // connect to the server, send the packet, and then read in the return packet.

  struct sockaddr_in serv_addr; // Server address data structure.
  struct hostent *server;       // Server data structure.

  sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Create a UDP socket.

  if (sockfd < 0)
    error("ERROR opening socket");

  server = gethostbyname(host_name); // Convert URL to IP.

  if (server == NULL)
    error("ERROR, no such host");

  // Zero out the server address structure.

  bzero((char *)&serv_addr, sizeof(serv_addr));

  serv_addr.sin_family = AF_INET;

  // Copy the server's IP address to the server address structure.

  bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);

  // Convert the port number integer to network big-endian style and save it to the server address structure.

  serv_addr.sin_port = htons(portno);

  // Call up the server using its IP address and port number.

  if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    error("ERROR connecting");

  // Send it the NTP packet it wants. If n == -1, it failed.

  n = write(sockfd, (char *)&packet, sizeof(ntp_packet));

  if (n < 0)
    error("ERROR writing to socket");

  // Wait and receive the packet back from the server. If n == -1, it failed.

  n = read(sockfd, (char *)&packet, sizeof(ntp_packet));

  if (n < 0)
    error("ERROR reading from socket");

  // These two fields contain the time-stamp seconds as the packet left the NTP server.
  // The number of seconds correspond to the seconds passed since 1900.
  // ntohl() converts the bit/byte order from the network's to host's "endianness".

  packet.txTm_s = ntohl(packet.txTm_s); // Time-stamp seconds.
  packet.txTm_f = ntohl(packet.txTm_f); // Time-stamp fraction of a second.

  // Extract the 32 bits that represent the time-stamp seconds (since NTP epoch) from when the packet left the server.
  // Subtract 70 years worth of seconds from the seconds since 1900.
  // This leaves the seconds since the UNIX epoch of 1970.
  // (1900)------------------(1970)**************************************(Time Packet Left the Server)

  time_t txTm = (time_t)(packet.txTm_s - NTP_TIMESTAMP_DELTA);

  // Print the time we got from the server, accounting for local timezone and conversion from UTC time.

  //printf( "Time: %s", ctime( ( const time_t* ) &txTm ) );

  return txTm;
}


ntp.h:
#ifndef HEADER_ntp
#define HEADER_ntp
/* ntp */

#include <time.h>

#define NTP_TIMESTAMP_DELTA 2208988800ull

#define LI(packet) (uint8_t)((packet.li_vn_mode & 0xC0) >> 6)   // (li   & 11 000 000) >> 6
#define VN(packet) (uint8_t)((packet.li_vn_mode & 0x38) >> 3)   // (vn   & 00 111 000) >> 3
#define MODE(packet) (uint8_t)((packet.li_vn_mode & 0x07) >> 0) // (mode & 00 000 111) >> 0

void error(char *msg);

time_t GetNtpTime(void);

#endif

main.c:
#include "ntp.h"
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

int main(int argc, char *argv[]) {

  time_t txTm = GetNtpTime();

  // Print the time we got from the server, accounting for local timezone and conversion from UTC time.

  printf("Time: %s", ctime((const time_t *)&txTm));

  return 0;
}


Zu den 10ms von der GPS Zeit. Ich denke nicht das das so genau funktionieren wird. Der GPS Empfänger gibt alle sekunde die Daten aus und das in der Regel mit 9600baud. Müsste man mal hoch rechnen.
 
"Code finden" klingt so, als wären Librarys erlaubt. Suche mal eine NTP-Library für C (damit du die Pakete nicht selbst bauen musst, die du vom Dienst empfängst).




Ich nehme mal an, das soll unter Linux laufen?

Möglichkeit 1: mit sudo aufrufen oder als root
Möglichkeit 2: setuid flag in der Binärdatei und ein Admin als Besitzer (Vorsicht)
Es sind sowohl Librarys erlaubt als auch fertige Codes ich soll nur die "Anpassung" übernehmen.

Soll unter Windows laufen

Kann man eine Datei so einrichten dass sie nur als Admin ausgeführt werden kann?
Das würde dieses Problem ja bereits lösen.
 
Ich las was von NTP... vllt hilf es ja

ntp.c:
#include "ntp.h"
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

void error(char *msg) {
  perror(msg); // Print the error message to stderr.
  exit(0);     // Quit the process.
}

time_t GetNtpTime(void) {

  int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket.

  int portno = 123; // NTP UDP port number.

  char *host_name = "de.pool.ntp.org"; // NTP server host-name.

  // Structure that defines the 48 byte NTP packet protocol.

  typedef struct {

    uint8_t li_vn_mode; // Eight bits. li, vn, and mode.
                        // li.   Two bits.   Leap indicator.
                        // vn.   Three bits. Version number of the protocol.
                        // mode. Three bits. Client will pick mode 3 for client.

    uint8_t stratum;   // Eight bits. Stratum level of the local clock.
    uint8_t poll;      // Eight bits. Maximum interval between successive messages.
    uint8_t precision; // Eight bits. Precision of the local clock.

    uint32_t rootDelay;      // 32 bits. Total round trip delay time.
    uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source.
    uint32_t refId;          // 32 bits. Reference clock identifier.

    uint32_t refTm_s; // 32 bits. Reference time-stamp seconds.
    uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second.

    uint32_t origTm_s; // 32 bits. Originate time-stamp seconds.
    uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second.

    uint32_t rxTm_s; // 32 bits. Received time-stamp seconds.
    uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second.

    uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
    uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second.

  } ntp_packet; // Total: 384 bits or 48 bytes.

  // Create and zero out the packet. All 48 bytes worth.

  ntp_packet packet = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

  memset(&packet, 0, sizeof(ntp_packet));

  // Set the first byte's bits to 00,011,011 for li = 0, vn = 3, and mode = 3. The rest will be left set to zero.

  *((char *)&packet + 0) = 0x1b; // Represents 27 in base 10 or 00011011 in base 2.

  // Create a UDP socket, convert the host-name to an IP address, set the port number,
  // connect to the server, send the packet, and then read in the return packet.

  struct sockaddr_in serv_addr; // Server address data structure.
  struct hostent *server;       // Server data structure.

  sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // Create a UDP socket.

  if (sockfd < 0)
    error("ERROR opening socket");

  server = gethostbyname(host_name); // Convert URL to IP.

  if (server == NULL)
    error("ERROR, no such host");

  // Zero out the server address structure.

  bzero((char *)&serv_addr, sizeof(serv_addr));

  serv_addr.sin_family = AF_INET;

  // Copy the server's IP address to the server address structure.

  bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);

  // Convert the port number integer to network big-endian style and save it to the server address structure.

  serv_addr.sin_port = htons(portno);

  // Call up the server using its IP address and port number.

  if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    error("ERROR connecting");

  // Send it the NTP packet it wants. If n == -1, it failed.

  n = write(sockfd, (char *)&packet, sizeof(ntp_packet));

  if (n < 0)
    error("ERROR writing to socket");

  // Wait and receive the packet back from the server. If n == -1, it failed.

  n = read(sockfd, (char *)&packet, sizeof(ntp_packet));

  if (n < 0)
    error("ERROR reading from socket");

  // These two fields contain the time-stamp seconds as the packet left the NTP server.
  // The number of seconds correspond to the seconds passed since 1900.
  // ntohl() converts the bit/byte order from the network's to host's "endianness".

  packet.txTm_s = ntohl(packet.txTm_s); // Time-stamp seconds.
  packet.txTm_f = ntohl(packet.txTm_f); // Time-stamp fraction of a second.

  // Extract the 32 bits that represent the time-stamp seconds (since NTP epoch) from when the packet left the server.
  // Subtract 70 years worth of seconds from the seconds since 1900.
  // This leaves the seconds since the UNIX epoch of 1970.
  // (1900)------------------(1970)**************************************(Time Packet Left the Server)

  time_t txTm = (time_t)(packet.txTm_s - NTP_TIMESTAMP_DELTA);

  // Print the time we got from the server, accounting for local timezone and conversion from UTC time.

  //printf( "Time: %s", ctime( ( const time_t* ) &txTm ) );

  return txTm;
}


ntp.h:
#ifndef HEADER_ntp
#define HEADER_ntp
/* ntp */

#include <time.h>

#define NTP_TIMESTAMP_DELTA 2208988800ull

#define LI(packet) (uint8_t)((packet.li_vn_mode & 0xC0) >> 6)   // (li   & 11 000 000) >> 6
#define VN(packet) (uint8_t)((packet.li_vn_mode & 0x38) >> 3)   // (vn   & 00 111 000) >> 3
#define MODE(packet) (uint8_t)((packet.li_vn_mode & 0x07) >> 0) // (mode & 00 000 111) >> 0

void error(char *msg);

time_t GetNtpTime(void);

#endif

main.c:
#include "ntp.h"
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

int main(int argc, char *argv[]) {

  time_t txTm = GetNtpTime();

  // Print the time we got from the server, accounting for local timezone and conversion from UTC time.

  printf("Time: %s", ctime((const time_t *)&txTm));

  return 0;
}


Zu den 10ms von der GPS Zeit. Ich denke nicht das das so genau funktionieren wird. Der GPS Empfänger gibt alle sekunde die Daten aus und das in der Regel mit 9600baud. Müsste man mal hoch rechnen.

Werde den Code später mal ausprobieren, wenn er funktioniert hast du mir sehr viel weitergeholfen.
Aber schonmal danke.

Die 10 ms Genauigkeit bezweifle ich auch sehr. Ja der GPS-Empfänger sendet ein Signal pro Sekunde mit 9600 baud.
Nicht nur da liegt das Problem, da Windows kein Echtzeitsystem ist kann man nie genau sagen wie lange schon nur das setzen des Zeitsignals dauert.
 
Soll unter Windows laufen

Dann wirst du den geposteten Code nicht ohne Weiteres verwenden können.. ich sehe da mindestens 2-3 Linux-Librarys.

Kann man eine Datei so einrichten dass sie nur als Admin ausgeführt werden kann?
Das würde dieses Problem ja bereits lösen.

Man kann es zB über Powershell mit erhöhten Rechten starten: start -Verb RunAs -FilePath bla.exe, eine Verknüpfung erstellen, die es immer als Admin startet, oder Strg+Shift gedrückt halten und dann die Datei ausführen. Das kann man ohne viel Aufwand mal eben so machen.

Wenn es von Haus aus erhöhte Rechte anfordern soll, muss das im Code geschehen. Aber ich kenne die Windows-API für C nicht. Ist es das hier https://docs.microsoft.com/en-us/windows/win32/api/ (oder ist das exklusiv C++)? Vielleicht weiß das ja jemand.

Edit: Vielleicht eher das hier https://docs.microsoft.com/en-us/cpp/c-language/?view=vs-2019
 
Zuletzt bearbeitet:
Dann wirst du den geposteten Code nicht ohne Weiteres verwenden können.. ich sehe da mindestens 2-3 Linux-Librarys.



Man kann es zB über Powershell mit erhöhten Rechten starten: start -Verb RunAs -FilePath bla.exe, eine Verknüpfung erstellen, die es immer als Admin startet, oder Strg+Shift gedrückt halten und dann die Datei ausführen. Das kann man ohne viel Aufwand mal eben so machen.

Wenn es von Haus aus erhöhte Rechte anfordern soll, muss das im Code geschehen. Aber ich kenne die Windows-API für C nicht. Ist es das hier https://docs.microsoft.com/en-us/windows/win32/api/ (oder ist das exklusiv C++)? Vielleicht weiß das ja jemand.

Edit: Vielleicht eher das hier https://docs.microsoft.com/en-us/cpp/c-language/?view=vs-2019

Das Problem mit den Librarys habe ich auch bei einem weiteren NTP-Code habe bisher noch keinen für Windows gefunden :|

ich habe mal die einfachste Variante umgesetzt indem ich in den Eigenschaften der vom Code erzeugten Exe eingestellt habe das diese nur als Admin ausführbar ist.
Damit kann ich nun zumindest die Uhrzeit setzen was ein guter Fortschritt ist.

Aber bei dem NTP-Client Aufruf komm ich nicht wirklich weiter...
 
Zurück
Oben Unten