Forum: Mikrocontroller und Digitale Elektronik Webserver mit UIP Stack und NTP-Client


von gerhard99 (Gast)


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

von Peter B. (pbuenger)


Lesenswert?

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

von gerhard99 (Gast)


Lesenswert?

Hallo Peter,

da habe ich ja richtig Glück! Meine Adresse lautet gs2006 bei arcor.de. 
Tausche bitte "bei" gegen "@".

Vielen Dank

Gerhard

von Peter B. (pbuenger)


Lesenswert?

Ok, kommt irgendwann heute Abend.

Gruß,
Peter

von Martin (Gast)


Lesenswert?

Hallo.
Ich haette auch Interesse an der UIP Version!
Kannst du dir mir bitte auch mal mailen?
maddinhoffmann -at- web.de

Danke!

von Torsten L. (torstenlabs)


Lesenswert?

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!!!!

von CODER (Gast)


Lesenswert?

Oder den Code hier als Anhang...nur als Idee....

von Peter B. (pbuenger)


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

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
Noch kein Account? Hier anmelden.