uIP+httpd+Daten zum Webserver senden

OP #2851581
Lesenswert?

Hallo Zusammen,

ich nutze den uIP sowie den zugehörigen Web Server von Adam Dunkel.
Per cgi-calls kann ich auch Daten von meinem uC im Web-Client 
darstellen.

Nun möchte ich aber Daten im Web Client in ein Textfeld eingeben und per 
Knopfdruck an den Web Server schicken.
Könnte mir evtl. jemand einen Link zu einem Code-Beispiel schicken, der 
zeigt, wie das prinzipiell funktioniert?
Per Butten kann ja ein GET-Befehl an den Web Server geschickt werden. 
Aber an welcher Stelle im httpd.c Code kann ich diese Daten dann 
abfangen und weiterverarbeiten? ode geht das dann auch über cgi?

Vielen Dank für Eure Hilfe.
Gruß
Stefan
#2851664
Lesenswert?

Nicht httpGET sondern httpPOST. Der Knopf im Formular macht dann 
"submit". Das kannst du bei der Auswertung des Headers im Server 
abfangen und passend verarbeiten.

Sieh dir als Beispiel mal den Radig Webserver an. Der ist zwar für einen 
anderen Stack und etwas buggy, aber für Anregungen prima geeignet, weil 
gut kommentiert.
#2851776
Lesenswert?

Stefan K. schrieb:

> Könnte mir evtl. jemand einen Link zu einem Code-Beispiel schicken, der
> zeigt, wie das prinzipiell funktioniert?

Hast du doch schon.
Die "Settings" Seite im httpd ist genau so gemacht.

> Aber an welcher Stelle im httpd.c Code kann ich diese Daten dann
> abfangen und weiterverarbeiten? ode geht das dann auch über cgi?


Sieh dir im httpd-cgi.c an, wie er da die "Settings" Seite reingebaut 
hat

Es beginnt ganz oben, wo er offenbar ein 'Schlüsselwort' "settings" mit 
einer auszuführenden Funktion verknüpft
1
HTTPD_CGI_CALL(cgi_settings, "settings", run_settings);

Diese Verknüpfung muss in die Tabelle der Verknüpfungen eingetragen 
werden
1
static const struct httpd_cgi_call *calls[] = 
2
{ 
3
    &cgi_hello,
4
    &cgi_settings, 
5
    &cgi_welcome,
6
    NULL 
7
};

aufgerufen wird die Funktion offenbar, weil in der settings.shtml
1
%!: /header.html
2
<h1>Network Settings</h1><br>
3
%! settings
4
%!: /footer.html
genau dieses Schlüsselwort "%! settings" vorkommt, was den http Server 
offenbar veranlasst die entsprechende Funktion aufzurufen.

Die Funktion selber ist ebenfalls in httpd-cgi.c enthalten
1
static PT_THREAD(run_settings(struct httpd_state *s, PGM_P ptr))
2
{
3
  //NOTE:local variables are not preserved during the calls to proto socket functins
4
  static uint8_t pcount;
5
  PSOCK_BEGIN(&s->sout);
6
  //check if there are parameters passed 
7
  if(s->param[0] && (pcount=http_get_parameters_parse(s->param,sizeof(s->param)))>0)
8
  {
9

10
    static uint8_t i,j;
11
    static uint8_t result;
12
    result=(pcount==4 || pcount==5 ); //correct number of parameters
13
    _enable_dhcp=0;
14
    //walk through parameters
15
    for(i=0;i<pcount;i++)
16
    {
17
      static char *pname,*pval;
18
      pname=http_get_parameter_name(s->param,i,sizeof(s->param));
19
      pval =http_get_parameter_value(s->param,i,sizeof(s->param));
20

21
      if(!strcmp_P(pname,PSTR("mac")) )
22
      {
23
        result = result && ( decode_mac(pval,_eth_addr) == 6);
24
      } else if(!strcmp_P(pname,PSTR("dhcp")) )
25
      {
26
        _enable_dhcp=(pval[0]=='1');
27
      } else if(!strcmp_P(pname,PSTR("ip")) )
28
      {
29

30
        result = result && (decode_ip(pval,_ip_addr)==4);
31
      } else if(!strcmp_P(pname,PSTR("netmask")) )
32
      {
33
        result = result && (decode_ip(pval,_net_mask)==4);
34
      } else if(!strcmp_P(pname,PSTR("gw")) )
35
      {
36
        result = result && (decode_ip(pval,_gateway)==4);
37
      } else {
38

39
#if DEBUG_SERIAL
40
        printf_P(PSTR("Unknown:%s = %s\r\n"),pname,pval);
41
#endif
42
        result=0; //unknown parameter, probably an error!
43
      }
44
    }
45
    if(result) {
46
      eeprom_write_byte(&ee_enable_dhcp,_enable_dhcp);
47
      eeprom_write_block (_eth_addr,&ee_eth_addr,6);
48
      eeprom_write_block (_ip_addr, &ee_ip_addr, 4);
49
      eeprom_write_block (_net_mask,&ee_net_mask,4);
50
      eeprom_write_block (_gateway, &ee_gateway, 4);
51
      
52
      PSOCK_SEND_PSTR(&s->sout,PSTR("<b>Parameters Accepted, cycle power to make active!</b>"));
53
    } else {
54
      PSOCK_SEND_PSTR(&s->sout,PSTR("<b>Parameters incorrect!</b>"));
55
    }
56
  }
57

58
  _enable_dhcp=eeprom_read_byte(&ee_enable_dhcp);;
59
  eeprom_read_block ((void *)_eth_addr,(const void *)&ee_eth_addr,6);
60
  eeprom_read_block ((void *)_ip_addr, (const void *)&ee_ip_addr, 4);
61
  eeprom_read_block ((void *)_net_mask,(const void *)&ee_net_mask,4);
62
  eeprom_read_block ((void *)_gateway, (const void *)&ee_gateway, 4);
63

64
  char temp[30];
65
  PSOCK_SEND_PSTR(&s->sout,PSTR("\
66
<form action=\"/settings.shtml\" method=\"get\" bgcolor=\"#808080\">\ 
67
<table>\
68
<tr><td>MAC:</td><td><input type=\"text\" name=\"mac\" size=\"18\" maxlength=\"18\" value=\""));
69

70
  snprintf_P(temp,sizeof(temp),PSTR("%02x:%02x:%02x:%02x:%02x:%02x"),
71
   (int)_eth_addr[0],(int)_eth_addr[1],(int)_eth_addr[2],
72
   (int)_eth_addr[3],(int)_eth_addr[4],(int)_eth_addr[5]);
73

74
  PSOCK_SEND_STR(&s->sout,temp);
75

76
  PSOCK_SEND_PSTR(&s->sout,PSTR("\"></td></tr>\
77
<tr><td>DHCP:</td><td><input type=\"checkbox\" name=\"dhcp\" value=\"1\""));
78

79
  if(_enable_dhcp) 
80
    PSOCK_SEND_PSTR(&s->sout,PSTR("CHECKED"));
81

82
  PSOCK_SEND_PSTR(&s->sout,PSTR("/></td></tr>\
83
<tr><td>IP:</td><td><input type=\"text\" name=\"ip\" size=\"15\" maxlength=\"15\" value=\""));
84

85
  snprintf_P(temp,sizeof(temp),PSTR("%d.%d.%d.%d"),
86
   (int)_ip_addr[0],(int)_ip_addr[1],(int)_ip_addr[2],(int)_ip_addr[3]);
87

88
  PSOCK_SEND_STR(&s->sout,temp);
89

90
PSOCK_SEND_PSTR(&s->sout,PSTR("\"></td></tr>\
91
<tr><td>Netmask:</td><td><input type=\"text\" name=\"netmask\" size=\"15\" maxlength=\"15\" value=\""));
92

93
  snprintf_P(temp,sizeof(temp),PSTR("%d.%d.%d.%d"),
94
   (int)_net_mask[0],(int)_net_mask[1],(int)_net_mask[2],(int)_net_mask[3]);
95

96
  PSOCK_SEND_STR(&s->sout,temp);
97

98
  PSOCK_SEND_PSTR(&s->sout,PSTR("\"/></td></tr>\
99
<tr><td>Gateway:</td><td><input type=\"text\" name=\"gw\" size=\"15\" maxlength=\"15\" value=\""));
100

101
  snprintf_P(temp,sizeof(temp),PSTR("%d.%d.%d.%d"),
102
   (int)_gateway[0],(int)_gateway[1],(int)_gateway[2],(int)_gateway[3]);
103

104
  PSOCK_SEND_STR(&s->sout,temp);
105

106
  PSOCK_SEND_PSTR(&s->sout,PSTR("\"/></td></tr>\
107
<tr align=\"justify\"><td colspan=2><INPUT TYPE=submit VALUE=\"Submit\">  <INPUT TYPE=reset VALUE=\"Reset\"></td></tr>\
108
</table></form>"));
109

110
  PSOCK_END(&s->sout);
111
}

und unterscheidet 2 Modi.
Wird sie mit oder ohne Parameter aufgerufen.
Ohne Parameter, der Fall kommt dann zum Zug, wenn die settings.shtml von 
einer anderen Seite verlinkt wurde und über diesen Link betreten wird.
Mit Parameter: Der Fall tritt deswegen ein, weil bei der Erzeugung des 
Formulars
1
... <form action=\"/settings.shtml\"  ....
wieder settings.shtml als Empfänger angegeben wurde


Das ist alles keine Raketentechnik. Aber ein wenig C sollte man schon 
können.
OP #2854247
Lesenswert?

Vielen Dank für die ausführliche Beschreibung.
Die Datei settings.shtml ist in meinem UIP-Stack + http Server nicht 
enthalten. Da gibts nur Beispiele für Status-Anzeigen und nichts zum 
Schreiben in Richtung http-Server.
Auf googlecode.com habe ich aber ein avr uhttpd Beispiel gefunden, dass 
deiner Beschreibung entspricht. Werde ich nun mal ausprobieren.
Also, noch mal vielen Dank.
Gruß
Stefan
Gast #4111035
Lesenswert?

Karl Heinz schrieb:
> Stefan K. schrieb:
>
>> Könnte mir evtl. jemand einen Link zu einem Code-Beispiel schicken, der
>> zeigt, wie das prinzipiell funktioniert?

> Sieh dir im httpd-cgi.c an, wie er da die "Settings" Seite reingebaut
> hat
>
> Es beginnt ganz oben, wo er offenbar ein 'Schlüsselwort' "settings" mit
> einer auszuführenden Funktion verknüpftHTTPD_CGI_CALL(cgi_settings,
> "settings", run_settings);

> Die Funktion selber ist ebenfalls in httpd-cgi.c enthaltenstatic
> PT_THREAD(run_settings(struct httpd_state *s, PGM_P ptr))


schade das läuft nicht unter keil
bei mir kommt der fehler
httpd-cgi.c(1526): error:  #136: struct "httpd_state" has no field 
"param"
Gast #4111618
Lesenswert?

Schau dir in httpd-functions.c zuerst die Funktion 
httpd_function_dispatcher() an, da wird je nach Parameter eine andere 
Unterfunktion aufgerufen.

Und in httpd.c kannst du dir anschauen, wie die URL in 
Dateiname/Funktionsname und Parameter gesplittet wird. Genau genommen 
wir gar nicht gesplittet, sondern nur zwei Pointer auf die Positionen 
gesetzt und Null-bytes eingefügt.
Gast #4112151
Lesenswert?

ich spiele ein bischen mit diesen 
Beitrag "ARM-Webserver auf uIP-Basis" Webserver.
Meine Leds kann ich damit schalten.
nun wollte ich in einem Textfeld etwas eingeben die seite wird mir auch 
angezeigt.
Aber die Variable pcount bleibt immer null.

könnte mir jemand weiterhelfen
danke

1
uint8_t http_get_parameters_parse(char *par,uint8_t mx)
2
{ 
3
  uint8_t count=0;
4
  uint8_t i=0;
5
  
6
  for(;par[i]&&i<mx;i++)
7
  {
8
    if(par[i]=='=') 
9
    {
10
      count++;
11
      par[i]=0;
12
    } else if(par[i]=='&')
13
      par[i]=0;
14
  }
15

16
  return count;
17
}
18

19
char * http_get_parameter_name(char *par,uint8_t cnt,uint8_t mx)
20
{
21
  uint8_t i,j;
22
  cnt*=2;
23
  for(i=0,j=0;j<mx&&i<cnt;j++)
24
    if(!par[j]) i++;
25

26
  return j==mx?"":par+j;
27
}
28

29
char * http_get_parameter_value(char *par,uint8_t cnt,uint8_t mx)
30
{
31
  uint8_t i,j;
32
  cnt*=2;
33
  cnt++;
34
  for(i=0,j=0;j<mx&&i<cnt;j++)
35
    if(!par[j]) i++;
36

37
  return j==mx?"":par+j;
38
}
39

40
void http_url_decode(const char *in,char *out,uint8_t mx)
41
{
42
  uint8_t i,j;
43
  char tmp[3]={0,0,0};
44
  for(i=0,j=0;j<mx&&in[i];i++)
45
  {
46
    if(in[i]=='%')
47
    {
48
      tmp[0]=in[++i];
49
      tmp[1]=in[++i];
50

51
      out[j++]=(char)strtol(tmp,NULL,16);
52
    } else 
53
      out[j++]=in[i];
54
  }
55
}
56

57
static uint8_t decode_ip(char *in,uint8_t *out)
58
{
59
  uint8_t i;
60
  char tmp[20];
61
  char *dig;
62
  strncpy(tmp,in,sizeof(tmp));
63
  
64
  dig=strtok(tmp,".");
65

66
  for(i=0 ; i<4 && dig ;i++,dig=strtok(NULL,"."))
67
    out[i]=(uint8_t)strtoul(dig,NULL,10);
68

69
  return i;
70
}
71

72
static uint8_t decode_mac(char *in,uint8_t *out)
73
{
74
  char tmp[20];
75
  char *dig;
76
  uint8_t i;  
77
  http_url_decode(in,tmp,sizeof(tmp)-1);
78

79

80
  
81
  dig=strtok(tmp,":");
82

83
  for(i=0 ; i<6 && dig ;i++,dig=strtok(NULL,":"))
84
    out[i]=(uint8_t)strtoul(dig,NULL,16);
85

86
  return i;
87
}
88

89

90

91

92

93
static PT_THREAD(run_settings(struct httpd_state *s, char *ptr))
94
{  char temp[30];
95
    static uint8_t i,j;
96
    static uint8_t result;
97
    static char *pname,*pval;  
98
  //NOTE:local variables are not preserved during the calls to proto socket functins
99
   uint8_t pcount;
100
    PSOCK_BEGIN(&s->sout);
101

102
  //check if there are parameters passed 
103
  if(s->param[0] && pcount=http_get_parameters_parse(s->param,sizeof(s->param)))>0)
104

105
  
106
  {
107

108

109
    result=(pcount==4 || pcount==5 ); //correct number of parameters
110
    _enable_dhcp=0;
111
    //walk through parameters
112
    for(i=0;i<pcount;i++)
113
    {
114
      
115
      pname=http_get_parameter_name(s->param,i,sizeof(s->param));
116
      pval =http_get_parameter_value(s->param,i,sizeof(s->param));
117

118
      
119
      if(!strcmp(pname,("mac")) )
120
      {  
121
        result = result && ( decode_mac(pval,_eth_addr) == 6);
122
      } 
123
      else if(!strcmp(pname,("dhcp")) )
124
      {  
125
        _enable_dhcp=(pval[0]=='1');
126
      } 
127
      else if(!strcmp(pname,("ip")) )
128
      {  
129

130
        result = result && (decode_ip(pval,_ip_addr)==4);
131
      } 
132
      else if(!strcmp(pname,("netmask")) )
133
      {  
134
        result = result && (decode_ip(pval,_net_mask)==4);
135
      } 
136
      else if(!strcmp(pname,("gw")) )
137
      {  
138
        result = result && (decode_ip(pval,_gateway)==4);
139
      } else {
140

141
#if DEBUG_SERIAL
142
        printf_P(PSTR("Unknown:%s = %s\r\n"),pname,pval);
143
#endif
144
        result=0; //unknown parameter, probably an error!
145
      }
146
    }
147
    if(result) {
148
      eeprom_write_byte(&ee_enable_dhcp,_enable_dhcp);
149
      eeprom_write_block (_eth_addr,&ee_eth_addr,6);
150
      eeprom_write_block (_ip_addr, &ee_ip_addr, 4);
151
      eeprom_write_block (_net_mask,&ee_net_mask,4);
152
      eeprom_write_block (_gateway, &ee_gateway, 4);
153
    
154
      PSOCK_SEND_STR(&s->sout,("Parameters Accepted, cycle power to make active!"));
155
    } else {
156
      PSOCK_SEND_STR(&s->sout,("Parameters incorrect!"));
157
    }
158
  }
159

160
  _enable_dhcp=eeprom_read_byte(&ee_enable_dhcp);;
161
  eeprom_read_block ((void *)_eth_addr,(const void *)&ee_eth_addr,6);
162
  eeprom_read_block ((void *)_ip_addr, (const void *)&ee_ip_addr, 4);
163
  eeprom_read_block ((void *)_net_mask,(const void *)&ee_net_mask,4);
164
  eeprom_read_block ((void *)_gateway, (const void *)&ee_gateway, 4);
165

166
  
167
  PSOCK_SEND_STR(&s->sout,("\<form action=\"/setting.shtml\" method=\"get\" bgcolor=\"#808080\">\<table>\<tr><td>MAC:</td><td><input type=\"text\" name=\"mac\" size=\"18\" maxlength=\"18\" value=\""));
168

169
  snprintf(temp,sizeof(temp),("%02x:%02x:%02x:%02x:%02x:%02x"),
170
   (int)_eth_addr[0],(int)_eth_addr[1],(int)_eth_addr[2],
171
   (int)_eth_addr[3],(int)_eth_addr[4],(int)_eth_addr[5]);
172

173
  PSOCK_SEND_STR(&s->sout,temp);
174

175
  PSOCK_SEND_STR(&s->sout,("\"></td></tr>\<tr><td>DHCP:</td><td><input type=\"checkbox\" name=\"dhcp\" value=\"1\""));
176

177
  if(_enable_dhcp) 
178
    PSOCK_SEND_STR(&s->sout,("CHECKED"));
179

180
  PSOCK_SEND_STR(&s->sout,("/></td></tr>\<tr><td>IP:</td><td><input type=\"text\" name=\"ip\" size=\"15\" maxlength=\"15\" value=\""));
181

182
  snprintf(temp,sizeof(temp),("%d.%d.%d.%d"),
183
   (int)_ip_addr[0],(int)_ip_addr[1],(int)_ip_addr[2],(int)_ip_addr[3]);
184

185
  PSOCK_SEND_STR(&s->sout,temp);
186

187
PSOCK_SEND_STR(&s->sout,("\"></td></tr>\<tr><td>Netmask:</td><td><input type=\"text\" name=\"netmask\" size=\"15\" maxlength=\"15\" value=\""));
188

189
  snprintf(temp,sizeof(temp),("%d.%d.%d.%d"),
190
   (int)_net_mask[0],(int)_net_mask[1],(int)_net_mask[2],(int)_net_mask[3]);
191

192
  PSOCK_SEND_STR(&s->sout,temp);
193

194
  PSOCK_SEND_STR(&s->sout,("\"/></td></tr>\<tr><td>Gateway:</td><td><input type=\"text\" name=\"gw\" size=\"15\" maxlength=\"15\" value=\""));
195

196
  snprintf(temp,sizeof(temp),("%d.%d.%d.%d"),
197
   (int)_gateway[0],(int)_gateway[1],(int)_gateway[2],(int)_gateway[3]);
198

199
  PSOCK_SEND_STR(&s->sout,temp);
200

201
  PSOCK_SEND_STR(&s->sout,("\"/></td></tr>\<tr align=\"justify\"><td colspan=2><INPUT TYPE=submit VALUE=\"Submit\">  <INPUT TYPE=reset VALUE=\"Reset\"></td></tr>\</table></form>"));
202

203
  PSOCK_END(&s->sout);
204
}
Angehängte Dateien:
Gast #4112251
Lesenswert?

Für meinen Geschmack ist das zuviel code um ihn rein theoretisch nur im 
Kopf durchzuanalysieren.

Nutze den seriellen Port, um Debug Meldungen zu loggen. Jede Funktion 
loggt am Anfange, dass sie aufgerufen wurde und mit welchen Parametern. 
Nach jedem if-Ausdruck loggst du das Ergebnis (ob es strue oder false 
ergab).

Damit kannst du Schrittweise herausfinden, was genau das Programm tut 
oder auch nicht tut. Oder verwende einen Hardware Debugger, falls 
verfügbar.
Gast #4115852
Lesenswert?

Hallo
So das beispiel funktioniert bei mir eigentlich ganz gut bis auf das ich 
den
button Submit 2mal anklicken muss damit die werte übernommen werden.
beim 1mal anklicken gehts nich.

nutze den aktuellen Mozilla

Woran könnte das liegen.

mfg

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