www.mikrocontroller.net

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


Autor: gerhard99 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Bünger (pbuenger)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: gerhard99 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

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

Vielen Dank

Gerhard

Autor: Peter Bünger (pbuenger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, kommt irgendwann heute Abend.

Gruß,
Peter

Autor: Martin (Gast)
Datum:

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

Danke!

Autor: Torsten Labs (torstenlabs)
Datum:

Bewertung
0 lesenswert
nicht 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!!!!

Autor: CODER (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder den Code hier als Anhang...nur als Idee....

Autor: Peter Bünger (pbuenger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, quick and dirty:

In der uip-Konfiguration UIP_UDP enablen. Dann den folgenden Appcall 
irgendwo einbauen:
/*-----------------------------------------------------------------------------------*/
/** \internal
 * The main UDP function.
 */
/*-----------------------------------------------------------------------------------*/
void
udp_appcall(void)
{
  if(uip_udp_conn->rport == HTONS(123)) {  // NTP protocol
    if(uip_poll()) {
      check_ntp_req();
    }
    if(uip_newdata()) {
      ntp_newdata();
    }       
  }

  // ....
  // weitere UDP Protokolle hierhin
  // ....
}

Die ntp-Routinen sehen so aus:
PROGMEM char NTP_Request[] = {0xd9, 0x00, 0x0a ,0xfa ,0x00 ,0x00,  
0x00 ,0x00 ,0x00 ,0x01 ,0x04 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, 
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00,  
0x00 ,0x00 ,0xca ,0x1a ,0xab ,0x0c ,0x48 ,0x7a ,0xe1 ,0x47};

#define GMT_TIME_CORRECTION  +3600    // +1h in seconds

struct {
#define STATE_IDLE   0
#define STATE_NEW    1
#define STATE_ASKING 2
#define STATE_ERROR  3
  u8_t state;
  u8_t tmr;
  u8_t retries;
} ntpstat;

static struct uip_udp_conn *ntp_conn = NULL;

/** \internal The maximum number of retries when asking for time. */
#define MAX_RETRIES 8

// Prüfen, ob eine ntp-Anfrage vorliegt. 
// Falls ja, ntp Request abschicken
void check_ntp_req(void) 
{
  char *ntpp;

  if (ntpstat.state == STATE_NEW)           // neue NTP-Anfrage?
     {
     ntpstat.state = STATE_ASKING;          // als "laufend" markieren
     ntpstat.tmr = 1;                       // Timer setzen
     ntpstat.retries = 0;                   // Wiederholungen zulassen
     }
     
  if (ntpstat.state == STATE_ASKING)        // laufende NTP-Anfrage?
     {
     if (--ntpstat.tmr == 0)                // Timer abgelaufen?
       {
       if(++ntpstat.retries == MAX_RETRIES) // max. Anzahl Wiederholungen erreicht?
         {
         ntpstat.state = STATE_ERROR;       // Fehler markieren
         return;                            // leider nichts mehr zu machen
         }
       ntpstat.tmr = ntpstat.retries;       // Timer wieder laden

       // Timer ist abgelaufen, Wiederholungen noch zulässig:
       // -> Request absenden
       ntpp = (char *)uip_appdata;          
       memcpy_P (ntpp, NTP_Request, sizeof(NTP_Request));
       uip_udp_send (sizeof(NTP_Request));
       }
     else                                   // Timer noch nicht abgelaufen:
       return;                              // weiter warten
     }
}

/*-----------------------------------------------------------------------------------*/
/** \internal
 * Called when new NTP data arrives.
 */
/*-----------------------------------------------------------------------------------*/
void ntp_newdata(void)
{
  unsigned long timestamp = 0L;
  unsigned char *swap1, *swap2;
  struct time current_time;
  struct timedata
    {
    char dummy[40];
    unsigned long t_time;
    } *str_udp;

  str_udp = (struct timedata *)uip_appdata;

  if(ntpstat.state == STATE_ASKING) 
    {
    // NTP request is now finished.
    ntpstat.state = STATE_IDLE;
    
    swap1 = (unsigned char *) &(str_udp->t_time);
    swap2 = (unsigned char *) &timestamp;
    swap2[0] = swap1[3]; swap2[1] = swap1[2]; swap2[2] = swap1[1]; swap2[3] = swap1[0];
    timestamp += GMT_TIME_CORRECTION;     //  UTC +1h

    conv_time(timestamp, &current_time);  // in struct time umrechnen
    printf_P(PSTR("NTP: Time is %02d.%02d.%04d  %02d:%02d:%02d  Day=%d\r\n"), 
                  current_time.day,  current_time.month,  current_time.year, 
                  current_time.hour, current_time.minute, current_time.second, current_time.wday);
    }
}

/*-----------------------------------------------------------------------------------*/
/**
 * Configure which NTP server to use for queries.
 *
 * \param ntpserver A pointer to a 4-byte representation of the IP
 * address of the NTP server to be configured.
 */
/*-----------------------------------------------------------------------------------*/
void ntp_conf(u16_t *ntpserver)
{
  if(ntp_conn != NULL) {
    uip_udp_remove(ntp_conn);
  }
  
  printf_P(PSTR("NTP uses Server %d.%d.%d.%d\r\n"), 
           ntpserver[0] & 0xFF, ntpserver[0] >> 8, 
           ntpserver[1] & 0xFF, ntpserver[1] >> 8);
  ntp_conn = uip_udp_new(ntpserver, 123);
}

/*-----------------------------------------------------------------------------------*/
/**
 * Initalize the ntp client.
 */
/*-----------------------------------------------------------------------------------*/
void ntp_init(void)
{
  ntpstat.state = STATE_IDLE;
}

void GetNTP_Time(void)
{
  ntpstat.state = STATE_NEW;
}

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:
#define FIRSTYEAR 1900     // start year
#define FIRSTDAY  1        // 0 = Sunday

void conv_time(unsigned long sec, struct time *t)
{
  u16_t day;
  u8_t  year;
  u16_t dayofyear;
  u8_t  leap400;
  u8_t  month;

  t->second = sec % 60;
  sec      /= 60;
  t->minute = sec % 60;
  sec      /= 60;
  t->hour   = sec % 24;
  day       = sec / 24;

  t->wday   = (day + FIRSTDAY) % 7;      // weekday

  year      = FIRSTYEAR % 100;           // 0..99
  leap400   = 4 - ((FIRSTYEAR - 1) / 100 & 3); // 4, 3, 2, 1

  for(;;)
    {
    dayofyear = 365;
    if((year & 3) == 0)
      {
      dayofyear = 366;                              // leap year
      if(year == 0 || year == 100 || year == 200)   // 100 year exception
        if(--leap400)                               // 400 year exception
          dayofyear = 365;
      }
    if(day < dayofyear)
      break;
    day -= dayofyear;
    year++;             // 00..136 / 99..235
    }
    
  t->year = year + FIRSTYEAR / 100 * 100; // + century

  if( dayofyear & 1 && day > 58 )      // no leap year and after 28.2.
    day++;                             // skip 29.2.

  for(month = 1; day >= DayOfMonth[month-1]; month++)
    day -= DayOfMonth[month-1];

  t->month = month;           // 1..12
  t->day   = day + 1;         // 1..31
}

Gruß,
Peter

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.