Wie funktioniert h2pas

Für Fragen von Einsteigern und Programmieranfängern...
Mathias
Beiträge: 7094
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Wie funktioniert h2pas

Beitrag von Mathias »

Ich habe mal udp.h probiert.

Code: Alles auswählen

h2pas -p -T -d -c -e udp.h 
at line 55 error : syntax error
at line 57 error : syntax error
at line 58 error : syntax error
at line 59 error : syntax error
at line 60 error : syntax error
at line 66 error : syntax error
at line 93 error : syntax error
at line 123 error : syntax error
at line 124 error : syntax error
at line 126 error : syntax error
at line 128 error : syntax error
at line 129 error : syntax error
at line 131 error : syntax error
at line 134 error : syntax error
at line 136 error : syntax error
at line 137 error : syntax error
at line 143 error : syntax error
at line 146 error : syntax error
at line 148 error : syntax error
at line 155 error : syntax error
at line 157 error : syntax error
at line 165 error : syntax error
at line 167 error : syntax error
Also hat es ab Zeile 55 Fehler.
Diese befinden sich in diesem Block:

Code: Alles auswählen

PACK_STRUCT_BEGIN
struct udp_hdr {
  PACK_STRUCT_FIELD(u16_t src);
  PACK_STRUCT_FIELD(u16_t dest);  /* src/dest UDP ports */
  PACK_STRUCT_FIELD(u16_t len);
  PACK_STRUCT_FIELD(u16_t chksum);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
Diese Struct ist leider unschön in Makros eingepackt.
Also schaut man was machen diese Makros:

Code: Alles auswählen

#ifndef PACK_STRUCT_BEGIN
#define PACK_STRUCT_BEGIN
#endif /* PACK_STRUCT_BEGIN */

#ifndef PACK_STRUCT_END
#define PACK_STRUCT_END
#endif /* PACK_STRUCT_END */

#ifndef PACK_STRUCT_FIELD
#define PACK_STRUCT_FIELD(x) x
#endif /* PACK_STRUCT_FIELD */
Die ersten beiden machen einen blank, somit kann man diese überell in der *.h entfernen. Auch der dritte macht nichts besonderes, kann auch entfernt werden.
Dann sehen die Zeilen so aus.

Code: Alles auswählen

struct udp_hdr {
  u16_t src;
  u16_t dest;  /* src/dest UDP ports */
  u16_t len;
  u16_t chksum;
} ;
Jetzt sieht es schon besser aus:

Code: Alles auswählen

 h2pas -p -T -d -c -e udp.h 
at line 93 error : syntax error
at line 123 error : syntax error
.....
Jetzt steckt ed da bei IP_PCB,

Code: Alles auswählen

struct udp_pcb {
/* Common members of all PCB types */
  IP_PCB;

/* Protocol specific PCB members */

  struct udp_pcb *next;

Dem geht man nach was das ist, hier habe ich es gefunden, es zeigt noch auf zusätliche Struct-Daten.

Code: Alles auswählen

#if LWIP_NETIF_HWADDRHINT
#define IP_PCB_ADDRHINT ;u8_t addr_hint
#else
#define IP_PCB_ADDRHINT
#endif /* LWIP_NETIF_HWADDRHINT */

/* This is the common part of all PCB types. It needs to be at the
   beginning of a PCB type definition. It is located here so that
   changes to this common part are made in one location instead of
   having to change all PCB structs. */
#define IP_PCB \
  /* ip addresses in network byte order */ \
  ip_addr_t local_ip; \
  ip_addr_t remote_ip; \
   /* Socket options */  \
  u8_t so_options;      \
   /* Type Of Service */ \
  u8_t tos;              \
  /* Time To Live */     \
  u8_t ttl               \
  /* link layer address resolution hint */ \
  IP_PCB_ADDRHINT
Ich sehe gerade, du hast ein echt harter Brocken zum übersetzen gefunden.
Ich habe jetzt weiter unten geguckt, da scheint es, wie es nur einen Pointer auf "udp_pcb" braucht.
Je nachdem wie das ganze aufgebaut ist, reicht es PAscal Seitig nur einen Pointer zu definieren. dies sieht dann so aus:

Code: Alles auswählen

type 
  Pudp_pcb = type Pointer;
Was meine Erfahrung gezeigt hat, ist, das diese komplexen struct meistens nur intern gebraucht werden.
Die scheint bei deinem Code auch der Fall zu sein, man beachte den * bei udp_pcb.

Code: Alles auswählen

extern struct udp_pcb *udp_pcbs;

/* The following functions is the application layer interface to the
   UDP code. */
struct udp_pcb * udp_new        (void)ICACHE_FLASH_ATTR;
void             udp_remove     (struct udp_pcb *pcb)ICACHE_FLASH_ATTR;
err_t            udp_bind       (struct udp_pcb *pcb, ip_addr_t *ipaddr,
                                 u16_t port)ICACHE_FLASH_ATTR;
err_t            udp_connect    (struct udp_pcb *pcb, ip_addr_t *ipaddr,
                                 u16_t port)ICACHE_FLASH_ATTR;
void             udp_disconnect (struct udp_pcb *pcb)ICACHE_FLASH_ATTR;
void             udp_recv       (struct udp_pcb *pcb, udp_recv_fn recv,
                                 void *recv_arg)ICACHE_FLASH_ATTR;
err_t            udp_sendto_if  (struct udp_pcb *pcb, struct pbuf *p,
                                 ip_addr_t *dst_ip, u16_t dst_port,
                                 struct netif *netif)ICACHE_FLASH_ATTR;
err_t            udp_sendto     (struct udp_pcb *pcb, struct pbuf *p,
                                 ip_addr_t *dst_ip, u16_t dst_port)ICACHE_FLASH_ATTR;
err_t            udp_send       (struct udp_pcb *pcb, struct pbuf *p)ICACHE_FLASH_ATTR;

#if LWIP_CHECKSUM_ON_COPY
err_t            udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p,
                                 ip_addr_t *dst_ip, u16_t dst_port,
                                 struct netif *netif, u8_t have_chksum,
                                 u16_t chksum)ICACHE_FLASH_ATTR;
err_t            udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p,
                                 ip_addr_t *dst_ip, u16_t dst_port,
                                 u8_t have_chksum, u16_t chksum)ICACHE_FLASH_ATTR;
err_t            udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
                                 u8_t have_chksum, u16_t chksum)ICACHE_FLASH_ATTR;
Ich hoffe ich konnte dir weiter helfen.

Sehe ich das richtig, die ganzen Header sind da, um mit dem PC mit ESP8266 zu kommunizieren ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wennerer
Beiträge: 647
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Wie funktioniert h2pas

Beitrag von wennerer »

Hallo Mathias,
vielen Dank für deine ausführliche Antwort!
Du hast mir auf jeden Fall weiter geholfen. Ich werde versuchen deinen Weg nach zu vollziehen. Mir geht es momentan auch gar nicht um eine spezielle Übersetzung sondern um Tipps wie man am Besten vor geht.
Sehe ich das richtig, die ganzen Header sind da, um mit dem PC mit ESP8266 zu kommunizieren ?
Ich habe mir mit FPCUpDeluxe eine Lazarusinstallation gebaut mit der ich einen ESP8266 programmieren kann.
viewtopic.php?p=151292#p151292
Kleine Sachen sind mir mit den Bindings von ccrause schon gelungen. Er hat mir auch schon weiter geholfen:
https://forum.lazarus.freepascal.org/in ... 082.0.html
Bindings für UDP hab ich bei ihm aber leider nicht gefunden.
Ich hab einen ESP laufen der die Energiedaten eines Verbrauchers mitschreibt und in eine Datei speichert. Die Verbindung funktioniert via UDP. Das Programm hab ich natürlich mit der Aduino IDE erstellt. Mein Ziel wäre es dies mit Lazarus auch zu schaffen. Aber für mich ist es ein noch viel härterer Brocken wie für dich :D .
Aber ich lerne ja gerne dazu.

Viele Grüße
Bernd

Mathias
Beiträge: 7094
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Wie funktioniert h2pas

Beitrag von Mathias »

Bindings für UDP hab ich bei ihm aber leider nicht gefunden.
Dann sind alle Header hier, für den ESP ?

https://github.com/nodemcu/nodemcu-firm ... clude/lwip

Dann wirst du noch eine Hürde habe, wie bindest du dies Libs in dein ESP-Pascal-Programm ein.
Sowas habe ich bis jetzt nie gemacht.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wennerer
Beiträge: 647
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon,Lazarus 2.2.6 (rev lazarus_2_2_6) FPC 3.2.2 x86_64-linux-
CPU-Target: x86_64-linux-gtk2

Re: Wie funktioniert h2pas

Beitrag von wennerer »

Dann sind alle Header hier, für den ESP ?
Ja die sind alle für den ESP8266. Und ja Hürden gibt es genug.
Aber wie schon gesagt viele Bindings sind im GitHub Repository von ccrause zu finden. Ich denke auch die libs für UDP dort gefunden zu haben. Ich hoffe mal wenn ich den Code noch lange genug anschaue zu einem Ergebnis zu kommen. Er hat da einen super Job gemacht!!!!

Jedenfalls hab ich schon einen mini Webserver mit zwei Button und einer LED erzeugen können. Die LED reagiert wie gewünscht. Jetzt möchte ich als nächstes einen Wert abrufen und anzeigen können.
EspHTTP.gif
EspHTTP.gif (57.39 KiB) 96 mal betrachtet
Das ist der Code dazu:

Code: Alles auswählen

program myfirsthttpserver;
uses
  fmem,
  wificonnect2,
  esp_http_server, esp_err, http_parser,
  portable, task, laz_esp, sysutils;

{$macro on}
{$inline on}

const
 AP_NAME  = //'DEINE_SSID';
 PWD      = //'DEIN_Netzwerkschlüssel';

var
 Chunk1  : PChar;
 Chunk2  : PChar;
 Chunk3  : PChar;
 WIZ1    : boolean;

procedure CreateWebpage;
begin
 writeln('CreateWebpage.....');
 Chunk1:= '<!DOCTYPE html><html>'+
           '<head>'+
            '<title>ESP8266 HTTP Server</title>'+
            '<style>'+
             'body {font-family: sans-serif;background-color:#302c2c}'+
             '.led-green {'+
             'margin-top: 6px;'+
             'width: 18px;'+
             'height: 18px;'+
             'background-color: greenyellow;'+
             'border-radius: 50%;'+
             'box-shadow: #000 0 -1px 7px 1px, inset #460 0 -1px 9px, #7D0 0 2px 12px;'+
             'float:left;}'+
             '.led-gray {'+
             'margin-top: 6px;'+
             'width: 18px;'+
             'height: 18px;'+
             'background-color: #C0C0C0;'+
             'border-radius: 50%;'+
             'box-shadow: #000 0 -1px 7px 1px, inset #9A9 0 -1px 9px, #969 0 2px 14px;'+
             'float:left;}'+
            '</style>'+
           '</head>'+
           '<form>'+
             '<h1><font color="snow">ESP8266 HTTP Server</font></h1>'+
             '<br><font color="snow">Maschine [Ein/Aus]:</font></br>';

  if WIZ1 then Chunk2 := '<div class="led-green"></div>';

  if not WIZ1 then Chunk2 := '<div class="led-gray"></div>';

  Chunk3 :=  '<style>input{color:white}</style>'+
             '<input type="submit" name="WIZ1" value="Ein" style=''Background-color: #6b7074;'+
             'font-family:Bradley Hand ITC; font-size: 24; font-weight: bold;width: 45px;'+
             'border-radius: 6px;border-width: 1px;border-color: snow;margin-top: 5px;margin-left:15px;''>'+

             '<input type="submit" name="WIZ1" value="Aus" style=''Background-color: #6b7074;'+
             'font-family:Bradley Hand ITC; font-size: 24; font-weight: bold;width: 45px;'+
             'border-radius: 6px;border-width: 1px;border-color: snow;margin-left: 5px;''>'+

             '<input type="text" name="WIZ1.1" value="0" size="9" style=''border-color:rgb(3, 3, 125);'+
             'border-width: 2px;border-style: solid;text-align: right;margin-left: 7px;'+
             'background-color:rgb(255, 255, 255);color:black;width: 70px;'' readonly>'+

             '<label style= "margin-left: 10px;color : snow">Watt</label>'+

            '</form>'+
           '</html>';

end;

function main_get_handler(req: Phttpd_req): Tesp_err;
var
  buf: PChar;
  buf_len: uint32;
  i : integer;
begin
  writeln('GetHandler');
  buf_len := httpd_req_get_hdr_value_len(req, 'Host') + 1;
  if (buf_len > 1) then
  begin
    buf := pvPortMalloc(buf_len);
    if (httpd_req_get_hdr_value_str(req, 'Host', buf, buf_len) = ESP_OK) then
      writeln('Found header => Host: ', buf);
    vPortFree(buf);
  end;

  buf_len := httpd_req_get_url_query_len(req) +1;
  if buf_len > 1 then
   begin
    buf := pvPortMalloc(buf_len);
    if httpd_req_get_url_query_str(req, buf,buf_len) = ESP_OK then
     writeln('Query: ', buf);

    i := Pos('WIZ1=Ein',buf);
    if i <> 0 then
     begin
      Wiz1 := true;
      writeln('WIZ1 ist ein');
     end;
    i := Pos('WIZ1=Aus',buf);
    if i <> 0 then
     begin
      Wiz1 := false;
      writeln('WIZ1 ist aus');
     end;

    vPortFree(buf);
   end;

  CreateWebpage;
  //httpd_resp_send(req, content, length(content));
  httpd_resp_send_chunk(req, Chunk1, length(Chunk1));
  httpd_resp_send_chunk(req, Chunk2, length(Chunk2));
  httpd_resp_send_chunk(req, Chunk3, length(Chunk3));
  // Signal finish of chunks
  httpd_resp_send_chunk(req, nil, 0);
  result := ESP_OK;
end;


function start_webserver: Thttpd_handle;
var
  server: Thttpd_handle;
  config: Thttpd_config;
  mainUriHandlerConfig: Thttpd_uri;

begin
  config := HTTPD_DEFAULT_CONFIG();

  with mainUriHandlerConfig do
  begin
    uri       := '/';
    method    := HTTP_GET;
    handler   := @main_get_handler;
    user_ctx  := nil;
  end;

  writeln('Starting server on port: ', config.server_port);
  if (httpd_start(@server, @config) = ESP_OK) then
  begin
    // Set URI handlers
    writeln('Registering URI handler');
    httpd_register_uri_handler(server, @mainUriHandlerConfig);
    result := server;
  end
  else
  begin
    result := nil;
    writeln('### Failed to start httpd');
  end;
end;


begin
  SerialBegin(9600);

  connectWifiAP(AP_NAME, PWD);

  writeln('Starting web server...');
  start_webserver;

  repeat
    vTaskDelay(10);
  until false;
end.

Viele Grüße
Bernd

Mathias
Beiträge: 7094
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Wie funktioniert h2pas

Beitrag von Mathias »

Ja die sind alle für den ESP8266. Und ja Hürden gibt es genug.
Aber wie schon gesagt viele Bindings sind im GitHub Repository von ccrause zu finden. Ich denke auch die libs für UDP dort gefunden zu haben. Ich hoffe mal wenn ich den Code noch lange genug anschaue zu einem Ergebnis zu kommen. Er hat da einen super Job gemacht!!!!
Werden dort die libs statisch eingebunden ?
Ich denke kaum, das man auf einen ESP *.so oder *.dll rauf laden kann.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 1005
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Wie funktioniert h2pas

Beitrag von PascalDragon »

Mathias hat geschrieben: Sa 8. Nov 2025, 15:25 Werden dort die libs statisch eingebunden ?
Ich denke kaum, das man auf einen ESP *.so oder *.dll rauf laden kann.
Ja, das Ergebnis ist eine statisch gelinkte Binary, die auf den MicroController geladen wird. Dynamisches Laden benötigt ein volles Betriebssystem.
FPC Compiler Entwickler

Antworten