Webserver mit UIP Stack und NTP-Client

Gast #643852
Lesenswert?

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
#848346
Lesenswert?

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 *) &timestamp;
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, &current_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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren