Hallo, ich versuche die Webserver-Version von Joachim Börke "Webserver zur Temperaturmessung V05" um eine NTP-Client Version zuerweitern, um die Uhrzeit aus dem Internet einzulesen. Alle Beispiele die ich gefunden habe beziehen sich auf die Version von U. Radig. Hier wird aber der UIP-Stack verwendet. Kann mir vielleicht einer weiterhelfen? Gruß Gerhard
Hallo Gerhard, habe ich erfolgreich am Laufen. Wenn Du willst, siche ich Dir meinen kompletten Source, kannst Dir dann die benötigten Teile rauskramen. Gruß, Peter
Hallo Peter, da habe ich ja richtig Glück! Meine Adresse lautet gs2006 bei arcor.de. Tausche bitte "bei" gegen "@". Vielen Dank Gerhard
Hallo. Ich haette auch Interesse an der UIP Version! Kannst du dir mir bitte auch mal mailen? maddinhoffmann -at- web.de Danke!
Hallo, ich hätte auch interessse an den Sourcen, kannst die sie mir bitte auch schicken? torstenlabs ät gmx.de das wäre super danke!!!!
Ok, quick and dirty: In der uip-Konfiguration UIP_UDP enablen. Dann den folgenden Appcall irgendwo einbauen:
1 | /*-----------------------------------------------------------------------------------*/
|
2 | /** \internal
|
3 | * The main UDP function.
|
4 | */
|
5 | /*-----------------------------------------------------------------------------------*/
|
6 | void
|
7 | udp_appcall(void) |
8 | {
|
9 | if(uip_udp_conn->rport == HTONS(123)) { // NTP protocol |
10 | if(uip_poll()) { |
11 | check_ntp_req(); |
12 | }
|
13 | if(uip_newdata()) { |
14 | ntp_newdata(); |
15 | }
|
16 | }
|
17 | |
18 | // ....
|
19 | // weitere UDP Protokolle hierhin
|
20 | // ....
|
21 | }
|
Die ntp-Routinen sehen so aus:
1 | PROGMEM char NTP_Request[] = {0xd9, 0x00, 0x0a ,0xfa ,0x00 ,0x00, |
2 | 0x00 ,0x00 ,0x00 ,0x01 ,0x04 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, |
3 | 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, |
4 | 0x00 ,0x00 ,0xca ,0x1a ,0xab ,0x0c ,0x48 ,0x7a ,0xe1 ,0x47}; |
5 | |
6 | #define GMT_TIME_CORRECTION +3600 // +1h in seconds
|
7 | |
8 | struct { |
9 | #define STATE_IDLE 0
|
10 | #define STATE_NEW 1
|
11 | #define STATE_ASKING 2
|
12 | #define STATE_ERROR 3
|
13 | u8_t state; |
14 | u8_t tmr; |
15 | u8_t retries; |
16 | } ntpstat; |
17 | |
18 | static struct uip_udp_conn *ntp_conn = NULL; |
19 | |
20 | /** \internal The maximum number of retries when asking for time. */
|
21 | #define MAX_RETRIES 8
|
22 | |
23 | // Prüfen, ob eine ntp-Anfrage vorliegt.
|
24 | // Falls ja, ntp Request abschicken
|
25 | void check_ntp_req(void) |
26 | {
|
27 | char *ntpp; |
28 | |
29 | if (ntpstat.state == STATE_NEW) // neue NTP-Anfrage? |
30 | {
|
31 | ntpstat.state = STATE_ASKING; // als "laufend" markieren |
32 | ntpstat.tmr = 1; // Timer setzen |
33 | ntpstat.retries = 0; // Wiederholungen zulassen |
34 | }
|
35 | |
36 | if (ntpstat.state == STATE_ASKING) // laufende NTP-Anfrage? |
37 | {
|
38 | if (--ntpstat.tmr == 0) // Timer abgelaufen? |
39 | {
|
40 | if(++ntpstat.retries == MAX_RETRIES) // max. Anzahl Wiederholungen erreicht? |
41 | {
|
42 | ntpstat.state = STATE_ERROR; // Fehler markieren |
43 | return; // leider nichts mehr zu machen |
44 | }
|
45 | ntpstat.tmr = ntpstat.retries; // Timer wieder laden |
46 | |
47 | // Timer ist abgelaufen, Wiederholungen noch zulässig:
|
48 | // -> Request absenden
|
49 | ntpp = (char *)uip_appdata; |
50 | memcpy_P (ntpp, NTP_Request, sizeof(NTP_Request)); |
51 | uip_udp_send (sizeof(NTP_Request)); |
52 | }
|
53 | else // Timer noch nicht abgelaufen: |
54 | return; // weiter warten |
55 | }
|
56 | }
|
57 | |
58 | /*-----------------------------------------------------------------------------------*/
|
59 | /** \internal
|
60 | * Called when new NTP data arrives.
|
61 | */
|
62 | /*-----------------------------------------------------------------------------------*/
|
63 | void ntp_newdata(void) |
64 | {
|
65 | unsigned long timestamp = 0L; |
66 | unsigned char *swap1, *swap2; |
67 | struct time current_time; |
68 | struct timedata |
69 | {
|
70 | char dummy[40]; |
71 | unsigned long t_time; |
72 | } *str_udp; |
73 | |
74 | str_udp = (struct timedata *)uip_appdata; |
75 | |
76 | if(ntpstat.state == STATE_ASKING) |
77 | {
|
78 | // NTP request is now finished.
|
79 | ntpstat.state = STATE_IDLE; |
80 | |
81 | swap1 = (unsigned char *) &(str_udp->t_time); |
82 | swap2 = (unsigned char *) ×tamp; |
83 | swap2[0] = swap1[3]; swap2[1] = swap1[2]; swap2[2] = swap1[1]; swap2[3] = swap1[0]; |
84 | timestamp += GMT_TIME_CORRECTION; // UTC +1h |
85 | |
86 | conv_time(timestamp, ¤t_time); // in struct time umrechnen |
87 | printf_P(PSTR("NTP: Time is %02d.%02d.%04d %02d:%02d:%02d Day=%d\r\n"), |
88 | current_time.day, current_time.month, current_time.year, |
89 | current_time.hour, current_time.minute, current_time.second, current_time.wday); |
90 | }
|
91 | }
|
92 | |
93 | /*-----------------------------------------------------------------------------------*/
|
94 | /**
|
95 | * Configure which NTP server to use for queries.
|
96 | *
|
97 | * \param ntpserver A pointer to a 4-byte representation of the IP
|
98 | * address of the NTP server to be configured.
|
99 | */
|
100 | /*-----------------------------------------------------------------------------------*/
|
101 | void ntp_conf(u16_t *ntpserver) |
102 | {
|
103 | if(ntp_conn != NULL) { |
104 | uip_udp_remove(ntp_conn); |
105 | }
|
106 | |
107 | printf_P(PSTR("NTP uses Server %d.%d.%d.%d\r\n"), |
108 | ntpserver[0] & 0xFF, ntpserver[0] >> 8, |
109 | ntpserver[1] & 0xFF, ntpserver[1] >> 8); |
110 | ntp_conn = uip_udp_new(ntpserver, 123); |
111 | }
|
112 | |
113 | /*-----------------------------------------------------------------------------------*/
|
114 | /**
|
115 | * Initalize the ntp client.
|
116 | */
|
117 | /*-----------------------------------------------------------------------------------*/
|
118 | void ntp_init(void) |
119 | {
|
120 | ntpstat.state = STATE_IDLE; |
121 | }
|
122 | |
123 | void GetNTP_Time(void) |
124 | {
|
125 | ntpstat.state = STATE_NEW; |
126 | }
|
Der vom ntp-Server gelieferte Timestamp zählt übrigens die Sekunden ab dem 01.01.1900, muss also noch geeignet umgerechnet werden. Bei mir sieht das so aus:
1 | #define FIRSTYEAR 1900 // start year
|
2 | #define FIRSTDAY 1 // 0 = Sunday
|
3 | |
4 | void conv_time(unsigned long sec, struct time *t) |
5 | {
|
6 | u16_t day; |
7 | u8_t year; |
8 | u16_t dayofyear; |
9 | u8_t leap400; |
10 | u8_t month; |
11 | |
12 | t->second = sec % 60; |
13 | sec /= 60; |
14 | t->minute = sec % 60; |
15 | sec /= 60; |
16 | t->hour = sec % 24; |
17 | day = sec / 24; |
18 | |
19 | t->wday = (day + FIRSTDAY) % 7; // weekday |
20 | |
21 | year = FIRSTYEAR % 100; // 0..99 |
22 | leap400 = 4 - ((FIRSTYEAR - 1) / 100 & 3); // 4, 3, 2, 1 |
23 | |
24 | for(;;) |
25 | {
|
26 | dayofyear = 365; |
27 | if((year & 3) == 0) |
28 | {
|
29 | dayofyear = 366; // leap year |
30 | if(year == 0 || year == 100 || year == 200) // 100 year exception |
31 | if(--leap400) // 400 year exception |
32 | dayofyear = 365; |
33 | }
|
34 | if(day < dayofyear) |
35 | break; |
36 | day -= dayofyear; |
37 | year++; // 00..136 / 99..235 |
38 | }
|
39 | |
40 | t->year = year + FIRSTYEAR / 100 * 100; // + century |
41 | |
42 | if( dayofyear & 1 && day > 58 ) // no leap year and after 28.2. |
43 | day++; // skip 29.2. |
44 | |
45 | for(month = 1; day >= DayOfMonth[month-1]; month++) |
46 | day -= DayOfMonth[month-1]; |
47 | |
48 | t->month = month; // 1..12 |
49 | t->day = day + 1; // 1..31 |
50 | }
|
Gruß, Peter
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.