HTTP client with WIFI plus click [Solved]

General discussion on mikroElektronika development boards.
Post Reply
Author
Message
Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

HTTP client with WIFI plus click [Solved]

#1 Post by Dany » 21 Apr 2023 13:39

Hi,

[Problem solved, see the last post in this thread]

Does anyone have an example how to retrieve a webpage from a regular HTTP server with the GET HTTP/1.1 request with the WIFI Plus module?
I do succeed in everything (including making a TCP connection to the HTTP server but I get an "Bad request 400" error from it...

Thanks in advance.

This is the full anwer I got from the server:
HTTP/1.0 400 Bad Request
Content-Length: 182
Content-Type: text/html; charset=utf-8
followed by:
<HTML><HEAD><TITLE>400 Bad Request (ERR_INVALID_REQ)</TITLE></HEAD><BODY><H1>400 Bad Request</H1><BR>ERR_INVALID_REQ<HR><B>Webserver</B> Sat, 22 Apr 2023 17:14:12 GMT</BODY></HTML>
This is my source code. I do use the mini32 board. I also do use Uart1 as debug input/output: All that comes in via Uart1 is sent to the HTTP server, all that is received from the HTTP server is sent to Uart1.
The Wifi Plus module is connected to Uart2.

Code: Select all

{*
 * Project name:
     WiFi_HTTP_Client
 * Copyright:
     none.
 * Revision History:

 * Description:

 * Test configuration:
     MCU:             P32MX534F064H
                      http://ww1.microchip.com/downloads/en/DeviceDoc/61156G.pdf
     Dev.Board:       MINI-32 Board
                      http://www.mikroe.com/eng/products/view/711/mini-32-board/
     Oscillator:      XT-PLL10x, 80.000MHz
     Ext. Modules:    None.
     SW:              mikroPascal PRO for PIC32
                      http://www.mikroe.com/eng/categories/view/89/pic32-compilers/
 * NOTES:
     - None.
*}

program WiFi_HTTP_Client;

uses UartReceiver_P32;

const UartBuffSize = 250;                     // for UartReceiver
var UartBuffer: array[UartBuffSize] of byte;  // for UartReceiver

var Redled_lat: sbit at LATG6_bit;
    Redled_tris: sbit at TRISG6_bit;
    OrangeLed_lat: sbit at LATD6_bit;
    OrangeLed_tris: sbit at TRISD6_bit;

var cnt, kk : byte;

var readbuff : array[64] of byte;
var writebuff : array[64] of byte;
var Priority: byte;

var Net_Wireless_MCW1001_Chip_RST: sbit at LATE1_bit;
    Net_Wireless_MCW1001_Chip_RST_Direction: sbit at TRISE1_bit;

var
    wifiStatus,
    SocketHandle,
    response,
    bindResult,
    listenresponse,
    backlog:  byte;

var strSSID:  string[50];
var wpaPassword:  string[50];
var channels:  array[11] of byte;
var myMacAddr:  array[6] of byte;
var ipMask:  array[4] of byte;

var remoteIP:  array[4] of byte;
var remotePort:  word;
var localPort:  word;

var myIpAddr:  array[4] of byte;
var gwIpAddr:  array[4] of byte;

var  wifiTmr:  integer;
    netStatusTmr: word;


procedure Tmr1_int(); iv IVT_TIMER_1; ilevel 6; ics ICS_SOFT;
begin
  if T1IF_bit then
  begin
    T1IF_bit         := 0;
    netStatusTmr := netStatusTmr + 1;

    wifiTmr := wifiTmr + 1;
    if wifiTmr >= 25 then
    begin
      Net_Wireless_MCW1001_Time := Net_Wireless_MCW1001_Time + 1;
      wifiTmr := 0;
    end;
  end;
end;

procedure Uart1_Int(); iv IVT_UART_1; ilevel 7; ics ICS_SRS;
begin
  UartReceiverInterrupt;
end;

procedure Uart2_int(); iv IVT_UART_2; ilevel 5; ics ICS_SOFT;
begin
  if U2RXIF_Bit then
  begin
    U2RXIF_bit := 0;
    if Uart_Data_ready = 1 then Net_Wireless_MCW1001_Receive;
  end;
  if U2TxIF_bit then U2TXIF_bit := 0;
end;

procedure Uart1_Write_Text_CRLF(var str: string);
begin
  Uart1_Write_Text(Str);
  Uart1_write(#13);
  Uart1_write(#10);
end;

procedure InitTimer1();
begin
  T1CON      := 0x8020;
  T1IP0_bit  := 1;
  T1IP1_bit  := 1;
  T1IP2_bit  := 1;
  T1IF_bit   := 0;
  PR1        := 50000;
  TMR1       := 0;
end;

procedure initNetwork;
begin

(*
/*
 * Before compiling this project, it's mandatory to modify
 *   this file acording to access point configurations
 *     to which the connection will be established.
 */
*)

  // set mac address
  myMacAddr[0] := 0x00;
  myMacAddr[1] := 0x04;
  myMacAddr[2] := 0xA3;
  myMacAddr[3] := 0x00;
  myMacAddr[4] := 0x80;
  myMacAddr[5] := 0x95;

  // set my IP address
  myIpAddr[0] := 192;
  myIpAddr[1] := 168;
  myIpAddr[2] := 123;
  myIpAddr[3] := 85;

  // set remote IP address (e.g. PC IP address)
  {-$DEFINE Mine}

  {$IFDEF Mine}
  remoteip[0] := 192;
  remoteip[1] := 168;
  remoteip[2] := 123;
  remoteip[3] := 69;
  {$ELSE}
  remoteip[0] := 192; // modem/router
  remoteip[1] := 168;
  remoteip[2] := 123;
  remoteip[3] := 254;
  {$ENDIF}
  
  // set gateway address
  gwIpAddr[0]  := 192;
  gwIpAddr[1]  := 168;
  gwIpAddr[2]  := 123;
  gwIpAddr[3]  := 254;

  // set subnet mask
  ipMask[0]    := 255;
  ipMask[1]    := 255;
  ipMask[2]    := 255;
  ipMask[3]    := 0;

  channels[0]  := 1;
  channels[1]  := 2;
  channels[2]  := 3;
  channels[3]  := 4;
  channels[4]  := 5;
  channels[5]  := 6;
  channels[6]  := 7;
  channels[7]  := 8;
  channels[8]  := 9;
  channels[9]  := 10;
  channels[10] := 11;

  strSSID:= 'xxxxxx';
  wpaPassword := 'yyyyyy';

  remotePort := 80;
  localPort := 40000;
end;

Procedure init_wifi();
begin
  Uart1_Write_Text('Configuration in Progress');

  Net_Wireless_MCW1001_TimeToWait := 2;
  Response:=1;

  while Response > 0 do
  begin
    response:= Net_Wireless_MCW1001_SetMode(_NET_WIRELESS_MCW1001_CP_1, _NET_WIRELESS_MCW1001_MODE_INFRASTRUCTURE);
    //wordtoStr(Response, Str);
    //Uart1_Write_Text_CRLF(Str);
    Uart1_write('.');
  end;
  Uart1_write_text_CRLF('');

  Net_Wireless_MCW1001_TimeToWait := 10;
  //Net_Wireless_MCW1001_InitDHCP();

  if response = 0 then response := Response or Net_Wireless_MCW1001_SetChannelList(1 {sizeof(channels)} , channels);  // <-------------
  if Response = 0 then Response := Response or Net_Wireless_MCW1001_SetSecurity_WPA(_NET_WIRELESS_MCW1001_CP_1, _NET_WIRELESS_MCW1001_WPA_PSK2, wpapassword);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetSSID(_NET_WIRELESS_MCW1001_CP_1, strSSID);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetNetworkMask(ipMask);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetGatewayIP(gwIpAddr);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetIP(myIpAddr);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetMAC(myMacAddr);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetArpTime(1);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetRetryCount(5, 255);  // Retrying the network connection forever.

  if (response > 0) then // Error
  begin
    Uart1_write_text_CRLF('Init Wifi ERROR!');
    while true do
    begin
      delay_ms(500);
      Redled_lat := not redled_lat;
    end;
  end
  else
  begin
    Uart1_Write_Text_CRLF('Init Wifi Success!');
  end;
end;

Procedure ConnectToAp();
var Res: string[10];
begin

  Uart1_Write_Text_CRLF('Connecting to AP, takes a while...');

  // Connect to AP
  Net_Wireless_MCW1001_TimeToWait := 40;

  response := Net_Wireless_MCW1001_Connect(_NET_WIRELESS_MCW1001_CP_1, wifiStatus);

  Net_Wireless_MCW1001_TimeToWait := 5;

  while ((response <> 0) or (wifiStatus <> 1) ) do                           // Probably need to edit networkPrameters.h file
  begin

    Uart1_Write_Text_CRLF('Connecting to AP FAILED');

    wordtoStr(Response, Res);

    Uart1_write_text('response:     ');
    Uart1_Write_Text_CRLF(Res);

    wordtoStr(WiFiStatus, Res);

    Uart1_write_text('Wifi status:  ');
    Uart1_Write_Text_CRLF(Res);

    Net_Wireless_MCW1001_TimeToWait := 40;

    response := Net_Wireless_MCW1001_Connect(_NET_WIRELESS_MCW1001_CP_1, wifiStatus);
  end;

  if response = 0 then
  begin
    Uart1_write_text_CRLF('Connecting to AP success');
    wordtoStr(WiFiStatus, Res);

    Uart1_write_text('Wifi status:  ');
    Uart1_Write_Text_CRLF(Res);
  end;

end;

//
procedure TCP_Setup();
var ConnectCnt: integer;
    res: string[10];
    ConnectResponse: byte;
begin
  response := Net_Wireless_MCW1001_SocketCreate(SocketHandle,_NET_WIRELESS_MCW1001_SOCKET_TYPE_TCP);
  if(response = _NET_WIRELESS_MCW1001_NO_ERROR) then
  begin
    Uart1_Write_Text_CRLF('Socket is OK');
    Uart1_write_text('Handle: ');
    bytetostr(SocketHandle, res);
    uart1_write_text_CRLF(res);
  end;

  response := Net_Wireless_MCW1001_SocketBind(SocketHandle, localPort, bindResult);
  if(response = 0) then
  begin
    Uart1_Write_Text_CRLF('Bind is OK');
    Uart1_write_text('Bindresult: ');
    bytetostr(bindresult, res);
    uart1_write_text_CRLF(res);

    for connectCnt := 0 to 4 do
    begin
      response := Net_Wireless_MCW1001_TCP_Connect(SocketHandle, remotePort, remoteIp {Net_Wireless_MCW1001_Properties.gatewayAddress},  connectResponse);
      Uart1_write_text('TCP_Connect response: ');
      Bytetostr(connectresponse, res);
      Uart1_write_text_CRLF(Res);
      
      if(connectResponse = 0) then // success
      begin
        Uart1_write_text_CRLF('TCP_Connect Success ');
        break;
      end
      else
      begin
        delay_ms(500);
      end;
    end;
    if (connectResponse <> 0) then Uart1_write_text_CRLF('TCP_Connect Failed');
  end else
  begin
    Uart1_Write_Text_CRLF('Bind FAILED');
  end;
end;

procedure CheckTcpReceive();
var
    response, i : byte;
    dat, TxBuffer     : string[255];
    numOfReceiveBytes : word;
    numOfSentBytes : word;
    Str: string[10];
    ConnectResponse: byte;
begin
  //response := Net_Wireless_MCW1001_TCP_Connect(SocketHandle, remotePort, remoteIp {Net_Wireless_MCW1001_Properties.gatewayAddress},  connectResponse);
  
  numOfReceiveBytes := 0;
  response := Net_Wireless_MCW1001_TCP_ReadBytes(SocketHandle, SizeOf(dat), @dat[0], numOfReceiveBytes);
  
  //bytetostr(response, Str);
  //Uart1_write_text_CRLF(Str);
  
  //exit;
  
  // If there is no error, and number of received bytes is greater than zero
  if( (response = _NET_WIRELESS_MCW1001_NO_ERROR) and (numOfReceiveBytes <> 0) ) then
  begin

    for i := 0 to numOfReceiveBytes - 1 do Txbuffer[I] := Dat[i];
    {
    NumOfSentBytes := NumOfReceiveBytes;
    Net_Wireless_MCW1001_TCP_SendBytes(socketChild, @txBuffer, numOfReceiveBytes, numOfSentBytes);
    }
    Uart1_Write_Text_CRLF('Received:       ');
    txBuffer[numOfReceiveBytes + 1] := 0;
    Uart1_Write_Text_CRLF(txBuffer);
  end;
end;

var Sendtxt: string[100];

procedure CheckToSend;
var receive, NumOfSentBytes, I, L: byte;
    txBuffer : string[255];
    str: string[10];
begin
  while UartCharPresent do
  begin
    OrangeLed_Lat := not orangeLed_Lat;
    
    Receive := ReadUartByte;
    
    if (receive <> 13) and (receive <> 10) then
    begin
      SendTxt := Sendtxt + char(Receive); // fill buffer
    end 
    else 
    if (receive = 13) // CR
    then
    begin // send command to the host
      RedLed_Lat := not RedLed_Lat;
      memset(@TxBuffer, 0, sizeOf(TxBuffer));
      
      L := length(SendTxt);
      for I := 0 to L-1 do Txbuffer[I] := SendTxt[I];
      
      TxBuffer[L] := #13;
      TxBuffer[L+1] := #10;
      TxBuffer[L+2] := #13;
      TxBuffer[L+3] := #10;
      
      // echo the text back to the uart
      Uart1_write_text(TxBuffer);
      
      Net_Wireless_MCW1001_TCP_SendBytes(SocketHandle, @txBuffer, length(TxBuffer), numOfSentBytes);
      
      SendTxt := '';
    end;
  end;
end;

procedure InitMcu;
begin
  AD1PCFG := 0xFFFF;                    // Configure AN pins as digital I/O
  Redled_tris := 0;
  Orangeled_tris := 0;

  Redled_lat := 0;
  Orangeled_Lat := 0;

  TRISE.0 := 0;

  // timer1
  InitTimer1;
  Priority := 6;
  T1Ip0_bit := Priority.0;
  T1IP1_bit := Priority.1;
  T1IP2_Bit := Priority.2;
  // timer1 interrupt enabled later (after initNetwork)

  Uart2_Init(115200);
  Uart1_init(115200);
  delay_ms(500);
  Uart_Set_Active(@UART2_Read, @UART2_Write, @UART2_Data_Ready, @UART2_Tx_Idle);

  // Uart1
  Priority := 7;
  U1IP0_bit := Priority.0;
  U1IP1_bit := Priority.1;
  U1IP2_bit := Priority.2;
  U1RXIF_Bit := 0;
  U1RXIE_bit := 1;

  // Uart2
  Priority := 5;
  U2IP0_bit := Priority.0;
  U2IP1_bit := Priority.1;
  U2IP2_bit := Priority.2;
  U2RXIF_Bit := 0;
  U2RXIE_bit := 1;
  
  SendTxt := '';

  UartReceiverInit;
   
  EnableInterrupts;
end;

procedure Scan;
var resp: byte;
    Str: string[50];
    I, J: word;
    Len: byte;
    numOfScanResult: byte;
begin
  // scan
  NumOfScanResult := 0;
  Resp := Net_Wireless_MCW1001_ScanStart(_NET_WIRELESS_MCW1001_CP_1, NumOfScanResult);

  // Show results
  bytetostr(NumOfScanResult, Str);
  uart1_write_text('Scanresults: ');
  Uart1_write_text_CRLF(Str);
  for i := 1 to NumOfScanResult do
  begin
    response := Net_Wireless_MCW1001_GetScanResult(i);
    Len := Net_Wireless_MCW1001_ScanResult.SSIDLength;
    Str := '                                                ';
    for J := 0 to Len - 1 do Str[J] := Net_Wireless_MCW1001_ScanResult.SSID[J];
    Rtrim(Str);
    Uart1_Write_text(Str);
    Uart1_Write_text(' ');
    bytetostr(Net_Wireless_MCW1001_ScanResult.Channel, Str);
    uart1_write_text_CRLF(str);
  end;
end;

begin
  InitMcu;

  Uart1_write_text_CRLF('');
  Uart1_Write_Text_CRLF('Started WiFi HTTP Client');

  Net_Wireless_MCW1001_HwReset();

  InitNetwork;
  T1Ie_bit := 1; // enable timer1

  init_wifi;
  Scan;
  ConnectToAP;
  TCP_Setup;
  while true do
  begin
    CheckToSend;
    CheckTcpReceive;
  end;
end.
Last edited by Dany on 28 Apr 2023 19:22, edited 2 times in total.
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: HTTP client with WIFI plus

#2 Post by Dany » 22 Apr 2023 19:44

Added some more details.
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: HTTP client with WIFI plus

#3 Post by Dany » 24 Apr 2023 15:30

In the mean time I succeeded in getting an 'OK' answer from the server. My GET request was totally inadequate.
I have the following request now:

Code: Select all

const Initrequest = 'GET / HTTP/1.1' + #13 + #10 +
                    'Host: 192.168.123.254'+ #13 + #10 +
                    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0' + #13 + #10 +
                    'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' + #13 + #10 +
                    'Accept-Language: nl,en-US;q=0.7,en;q=0.3' + #13 + #10 +
                    'Accept-Encoding: gzip, deflate' + #13 + #10 +
                    'DNT: 1' + #13 + #10 +
                    'Connection: keep-alive' + #13 + #10 +
                    'Upgrade-Insecure-Requests: 1' + #13 + #10 +
                    + #13 + #10;
The server now responds but keeps responding (I think forever). This is what the answer looks like:
Received:
HTTP/1.1 200 OK
Cache-Control: no-cache
Cache-Control: no-cache, no-store, must-revalidate
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Date: Mon, 24 Apr 2023 14:27:39 GMT
Expires: -1
Pragma: no-cache
KeHTTP/1.1 200 OK
Cache-Control: no-cache
Cache-Control: no-cache, no-store, must-revalidate
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Date: Mon, 24 Apr 2023 14:27:39 GMT
Expires: -1
Pragma: no-cache
KeHTTP/1.1 200 OK
Cache-Control: no-cache
Cache-Control: no-cache, no-store, must-revalidate
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Apr 2023 14:27:39 GMT
Expires: -1
Pragma: no-cache
KeHTTP/1.cache
Cache-Control: no-cache, no-store, must-revalidate
Connencoding: chunked
Content-Type: text/html; charset=utf-8
Date:
Expires: -1
Pragma: no-cache
KeHTTP/1.1 200 OK
and this goes on and on...

Anyone an idea?
Thanks in advance!
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: HTTP client with WIFI plus click

#4 Post by Dany » 28 Apr 2023 18:51

Hi, I did find my (stupid) error.
Thanks to everone who did ahve a look into my problem!

Code: Select all

var
    response, i : byte;
    [b]dat[/b], TxBuffer     :[b] string[255][/b];
    numOfReceiveBytes : word;
    numOfSentBytes : word;
    Str: string[10];
    ConnectResponse: byte;
begin
    numOfReceiveBytes := 0;
    response := Net_Wireless_MCW1001_TCP_ReadBytes(SocketHandle, [b]SizeOf(dat)[/b], @dat[0], numOfReceiveBytes);
   ...
    for i := 0 to numOfReceiveBytes - 1 do Txbuffer[I] := Dat[i];
    ...
    txBuffer[[b]numOfReceiveBytes[/b]] := 0;    
In above code it is so that Sizeof(dat) is 256 in stead of the 255 I had in mind. The statement "txBuffer[numOfReceiveBytes] := 0;" will write to TxBuffer[256], which does no exist: memory corruption.
So I changed variable "Dat" to an array of 255 bytes, and also made variable "I" a word to be sure.
Additionally I did send the received data too fast to uart1, my receiving program could not handle the high speed and missed some data, so I added a delay

This is the adapted code:

Code: Select all

{*
 * Project name:
     WiFi_HTTP_Client
 * Copyright:
     none.
 * Revision History:

 * Description:

 * Test configuration:
     MCU:             P32MX534F064H
                      http://ww1.microchip.com/downloads/en/DeviceDoc/61156G.pdf
     Dev.Board:       MINI-32 Board
                      http://www.mikroe.com/eng/products/view/711/mini-32-board/
     Oscillator:      XT-PLL10x, 80.000MHz
     Ext. Modules:    None.
     SW:              mikroPascal PRO for PIC32
                      http://www.mikroe.com/eng/categories/view/89/pic32-compilers/
 * NOTES:
     - None.
*}

program WiFi_HTTP_Client;

uses UartReceiver_P32;

const UartBuffSize = 1000;                    // for UartReceiver
var UartBuffer: array[UartBuffSize] of byte;  // for UartReceiver

var Redled_lat: sbit at LATG6_bit;
    Redled_tris: sbit at TRISG6_bit;
    OrangeLed_lat: sbit at LATD6_bit;
    OrangeLed_tris: sbit at TRISD6_bit;

var cnt, kk : byte;

var readbuff : array[64] of byte;
var writebuff : array[64] of byte;
var Priority: byte;

var Net_Wireless_MCW1001_Chip_RST: sbit at LATE1_bit;
    Net_Wireless_MCW1001_Chip_RST_Direction: sbit at TRISE1_bit;

var
    wifiStatus,
    SocketHandle,
    response,
    bindResult,
    listenresponse,
    backlog:  byte;

var strSSID:  string[50];
var wpaPassword:  string[50];
var channels:  array[11] of byte;
var myMacAddr:  array[6] of byte;
var ipMask:  array[4] of byte;

var remoteIP:  array[4] of byte;
var remotePort:  word;
var localPort:  word;

var myIpAddr:  array[4] of byte;
var gwIpAddr:  array[4] of byte;

var  wifiTmr:  integer;
    netStatusTmr: word;


procedure Tmr1_int(); iv IVT_TIMER_1; ilevel 6; ics ICS_SOFT;
begin
  if T1IF_bit then
  begin
    T1IF_bit         := 0;
    netStatusTmr := netStatusTmr + 1;

    wifiTmr := wifiTmr + 1;
    if wifiTmr >= 25 then
    begin
      Net_Wireless_MCW1001_Time := Net_Wireless_MCW1001_Time + 1;
      wifiTmr := 0;
    end;
  end;
end;

procedure Uart1_Int(); iv IVT_UART_1; ilevel 7; ics ICS_SRS;
begin
  UartReceiverInterrupt;
end;

procedure Uart2_int(); iv IVT_UART_2; ilevel 5; ics ICS_SOFT;
begin
  if U2RXIF_Bit then
  begin
    U2RXIF_bit := 0;
    if Uart_Data_ready = 1 then Net_Wireless_MCW1001_Receive;
  end;
  if U2TxIF_bit then U2TXIF_bit := 0;
end;

procedure Uart1_Write_Text_CRLF(var str: string);
begin
  Uart1_Write_Text(Str);
  Uart1_write(#13);
  Uart1_write(#10);
end;

procedure InitTimer1();
begin
  T1CON      := 0x8020;
  T1IP0_bit  := 1;
  T1IP1_bit  := 1;
  T1IP2_bit  := 1;
  T1IF_bit   := 0;
  PR1        := 50000;
  TMR1       := 0;
end;

procedure initNetwork;
begin

(*
/*
 * Before compiling this project, it's mandatory to modify
 *   this file acording to access point configurations
 *     to which the connection will be established.
 */
*)

  // set mac address
  myMacAddr[0] := 0x00;
  myMacAddr[1] := 0x04;
  myMacAddr[2] := 0xA3;
  myMacAddr[3] := 0x00;
  myMacAddr[4] := 0x80;
  myMacAddr[5] := 0x95;

  // set my IP address
  myIpAddr[0] := 192;
  myIpAddr[1] := 168;
  myIpAddr[2] := 123;
  myIpAddr[3] := 85;

  // set remote IP address (e.g. PC IP address)
   remoteip[0] := 192; // modem/router
  remoteip[1] := 168;
  remoteip[2] := 123;
  remoteip[3] := 254;
  
  // set gateway address
  gwIpAddr[0]  := 192;
  gwIpAddr[1]  := 168;
  gwIpAddr[2]  := 123;
  gwIpAddr[3]  := 254;

  // set subnet mask
  ipMask[0]    := 255;
  ipMask[1]    := 255;
  ipMask[2]    := 255;
  ipMask[3]    := 0;

  channels[0]  := 1;
  channels[1]  := 2;
  channels[2]  := 3;
  channels[3]  := 4;
  channels[4]  := 5;
  channels[5]  := 6;
  channels[6]  := 7;
  channels[7]  := 8;
  channels[8]  := 9;
  channels[9]  := 10;
  channels[10] := 11;

  strSSID:= '....';
  wpaPassword := '....';

  remotePort := 80;
  localPort := 1026;
end;

Procedure init_wifi();
begin
  Uart1_Write_Text('Configuration in Progress');

  Net_Wireless_MCW1001_TimeToWait := 2;
  Response:=1;

  while Response > 0 do
  begin
    response:= Net_Wireless_MCW1001_SetMode(_NET_WIRELESS_MCW1001_CP_1, _NET_WIRELESS_MCW1001_MODE_INFRASTRUCTURE);
    //wordtoStr(Response, Str);
    //Uart1_Write_Text_CRLF(Str);
    Uart1_write('.');
  end;
  Uart1_write_text_CRLF('');

  Net_Wireless_MCW1001_TimeToWait := 10;
  //Net_Wireless_MCW1001_InitDHCP();

  if response = 0 then response := Response or Net_Wireless_MCW1001_SetChannelList(1 {sizeof(channels)} , channels);  // <-------------
  if Response = 0 then Response := Response or Net_Wireless_MCW1001_SetSecurity_WPA(_NET_WIRELESS_MCW1001_CP_1, _NET_WIRELESS_MCW1001_WPA_PSK2, wpapassword);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetSSID(_NET_WIRELESS_MCW1001_CP_1, strSSID);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetNetworkMask(ipMask);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetGatewayIP(gwIpAddr);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetIP(myIpAddr);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetMAC(myMacAddr);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetArpTime(1);
  if response = 0 then response := Response or Net_Wireless_MCW1001_SetRetryCount(5, 255);  // Retrying the network connection forever.

  Net_Wireless_MCW1001_SocketAllocate(0, 1, 0, 0, 2048, 2048);           // Allocate byffers for sockets

  if (response > 0) then // Error
  begin
    Uart1_write_text_CRLF('Init Wifi ERROR!');
    while true do
    begin
      delay_ms(500);
      Redled_lat := not redled_lat;
    end;
  end
  else
  begin
    Uart1_Write_Text_CRLF('Init Wifi Success!');
  end;
end;

Procedure ConnectToAp();
var Res: string[10];
begin

  Uart1_Write_Text_CRLF('Connecting to AP, takes a while...');

  // Connect to AP
  Net_Wireless_MCW1001_TimeToWait := 40;

  response := Net_Wireless_MCW1001_Connect(_NET_WIRELESS_MCW1001_CP_1, wifiStatus);

  Net_Wireless_MCW1001_TimeToWait := 5;

  while ((response <> 0) or (wifiStatus <> 1) ) do                           // Probably need to edit networkPrameters.h file
  begin

    Uart1_Write_Text_CRLF('Connecting to AP FAILED');

    wordtoStr(Response, Res);

    Uart1_write_text('response:     ');
    Uart1_Write_Text_CRLF(Res);

    wordtoStr(WiFiStatus, Res);

    Uart1_write_text('Wifi status:  ');
    Uart1_Write_Text_CRLF(Res);

    Net_Wireless_MCW1001_TimeToWait := 40;

    response := Net_Wireless_MCW1001_Connect(_NET_WIRELESS_MCW1001_CP_1, wifiStatus);
  end;

  if response = 0 then
  begin
    Uart1_write_text_CRLF('Connecting to AP success');
    wordtoStr(WiFiStatus, Res);

    Uart1_write_text('Wifi status:  ');
    Uart1_Write_Text_CRLF(Res);
  end;

end;

//
procedure TCP_Setup();
var ConnectCnt: integer;
    res: string[10];
    ConnectResponse: byte;
begin
  response := Net_Wireless_MCW1001_SocketCreate(SocketHandle,_NET_WIRELESS_MCW1001_SOCKET_TYPE_TCP);
  if(response = _NET_WIRELESS_MCW1001_NO_ERROR) then
  begin
    Uart1_Write_Text_CRLF('Socket is OK');
    Uart1_write_text('Handle: ');
    bytetostr(SocketHandle, res);
    uart1_write_text_CRLF(res);
  end;

  //response := Net_Wireless_MCW1001_SocketBind(SocketHandle, localPort, bindResult);
  Response := 0;
  if(response = 0) then
  begin
    Uart1_Write_Text_CRLF('Bind is OK');
    Uart1_write_text('Bindresult: ');
    bytetostr(bindresult, res);
    uart1_write_text_CRLF(res);

    for connectCnt := 1 to 20 do
    begin
      response := Net_Wireless_MCW1001_TCP_Connect(SocketHandle, remotePort, remoteIp {Net_Wireless_MCW1001_Properties.gatewayAddress},  connectResponse);
      Uart1_write_text('TCP_Connect response: ');
      Bytetostr(connectresponse, res);
      Uart1_write_text_CRLF(Res);
      
      if(connectResponse = 0) then // success
      begin
        Uart1_write_text_CRLF('TCP_Connect Success ');
        break;
      end
      else
      begin
        delay_ms(1000);
      end;
    end;
    if (connectResponse <> 0) then Uart1_write_text_CRLF('TCP_Connect Failed');
  end else
  begin
    Uart1_Write_Text_CRLF('Bind FAILED');
  end;
end;

const Initrequest = 'GET / HTTP/1.1' + #13 + #10 +
                    'Host: 192.168.123.254'+ #13 + #10 +
                    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0' + #13 + #10 +
                    'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' + #13 + #10 +
                    'Accept-Language: nl,en-US;q=0.7,en;q=0.3' + #13 + #10 +
                    'Accept-Encoding: gzip, deflate' + #13 + #10 +
                    'DNT: 1' + #13 + #10 +
                    'Connection: keep-alive' + #13 + #10 +
                    //'Connection: close' + #13 + #10 +
                    'Upgrade-Insecure-Requests: 1' + #13 + #10 +
                    + #13 + #10;
                    
procedure PutConstString(const s : ^byte);
const MAX_SIZE_OF_DATA = 400;
var
  numOfSentBytes, bufferindex : word;
  txbuffer: array[500] of byte;
begin
  BufferIndex := 0;
  while(s^ <> 0) do
  begin
    txBuffer[bufferIndex] := s^;
    bufferIndex := bufferIndex + 1;
    s := s + 1;
    if(bufferIndex = MAX_SIZE_OF_DATA) then
    begin
      Net_Wireless_MCW1001_TCP_SendBytes(socketHandle, @txBuffer, MAX_SIZE_OF_DATA, numOfSentBytes);
      bufferIndex := 0;
    end;
  end;
  if Bufferindex > 0 then // some bytes left
  Net_Wireless_MCW1001_TCP_SendBytes(socketHandle, @txBuffer, BufferIndex, numOfSentBytes);
  BufferIndex := 0;
end;

procedure CheckTcpReceive();
var
    response: byte;
    dat: array[255] of byte; // <-- adapted
    TxBuffer     : string[255];
    I, // <-- adapted
    numOfReceiveBytes,
    numOfSentBytes : word;
    Str: string[10];
    ConnectResponse: byte;
begin
  //response := Net_Wireless_MCW1001_TCP_Connect(SocketHandle, remotePort, remoteIp {Net_Wireless_MCW1001_Properties.gatewayAddress},  connectResponse);
  
  Memset(@dat, 0, sizeof(Dat));
  Memset(@txBuffer, 0, sizeof(TxBuffer));
  
  numOfReceiveBytes := 0;
  response := Net_Wireless_MCW1001_TCP_ReadBytes(SocketHandle, SizeOf(dat), @dat[0], numOfReceiveBytes);
  
  //bytetostr(response, Str);
  //Uart1_write_text_CRLF(Str);
  
  //exit;
  
  // If there is no error, and number of received bytes is greater than zero
  if( (response = _NET_WIRELESS_MCW1001_NO_ERROR) and (numOfReceiveBytes > 0) ) then
  begin

    for i := 0 to numOfReceiveBytes - 1 do Txbuffer[I] := char(Dat[i]); // <-- adapted
   
    Uart1_Write_Text_CRLF('');
    Uart1_Write_Text_CRLF('');
    Uart1_Write_Text('--> Received: ');
    inttoStr(numOfReceivebytes, str); // <-- added
    Uart1_Write_Text(Str); // <-- added
    Uart1_Write_Text_CRLF(' <--'); 
    Uart1_Write_Text_CRLF('');
    txBuffer[numOfReceiveBytes] := 0;
    Uart1_Write_Text(txBuffer);
    delay_ms(100); // <-- added
  end;
end;

var Sendtxt: string[100];

procedure CheckToSend;
var receive, NumOfSentBytes, I, L: byte;
    txBuffer : string[255];
    str: string[10];
begin
  while UartCharPresent do
  begin
    OrangeLed_Lat := not orangeLed_Lat;
    
    Receive := ReadUartByte;
    
    if (receive <> 13) and (receive <> 10) then
    begin
      SendTxt := Sendtxt + char(Receive); // fill buffer
    end 
    else 
    if (receive = 13) // CR
    then
    begin // send command to the host
      RedLed_Lat := not RedLed_Lat;
      memset(@TxBuffer, 0, sizeOf(TxBuffer));
      
      L := length(SendTxt);
      for I := 0 to L-1 do Txbuffer[I] := SendTxt[I];
      
      TxBuffer[L] := #13;
      TxBuffer[L+1] := #10;
      TxBuffer[L+2] := #13;
      TxBuffer[L+3] := #10;
      
      // echo the text back to the uart
      //Uart1_write_text(TxBuffer);
      
      Net_Wireless_MCW1001_TCP_SendBytes(SocketHandle, @txBuffer, length(TxBuffer), numOfSentBytes);
      
      SendTxt := '';
    end;
  end;
end;

procedure InitMcu;
begin
  AD1PCFG := 0xFFFF;                    // Configure AN pins as digital I/O
  Redled_tris := 0;
  Orangeled_tris := 0;

  Redled_lat := 0;
  Orangeled_Lat := 0;

  TRISE.0 := 0;

  // timer1
  InitTimer1;
  Priority := 6;
  T1Ip0_bit := Priority.0;
  T1IP1_bit := Priority.1;
  T1IP2_Bit := Priority.2;
  // timer1 interrupt enabled later (after initNetwork)

  Uart2_Init(115200);
  Uart1_init(115200);
  delay_ms(500);
  Uart_Set_Active(@UART2_Read, @UART2_Write, @UART2_Data_Ready, @UART2_Tx_Idle);

  // Uart1
  Priority := 7;
  U1IP0_bit := Priority.0;
  U1IP1_bit := Priority.1;
  U1IP2_bit := Priority.2;
  U1RXIF_Bit := 0;
  U1RXIE_bit := 1;

  // Uart2
  Priority := 5;
  U2IP0_bit := Priority.0;
  U2IP1_bit := Priority.1;
  U2IP2_bit := Priority.2;
  U2RXIF_Bit := 0;
  U2RXIE_bit := 1;
  
  SendTxt := '';

  UartReceiverInit;
   
  EnableInterrupts;
end;

procedure Scan;
var resp: byte;
    Str: string[50];
    I, J: word;
    Len: byte;
    numOfScanResult: byte;
begin
  // scan
  NumOfScanResult := 0;
  Resp := Net_Wireless_MCW1001_ScanStart(_NET_WIRELESS_MCW1001_CP_1, NumOfScanResult);

  // Show results
  bytetostr(NumOfScanResult, Str);
  uart1_write_text('Scanresults: ');
  Uart1_write_text_CRLF(Str);
  for i := 1 to NumOfScanResult do
  begin
    response := Net_Wireless_MCW1001_GetScanResult(i);
    Len := Net_Wireless_MCW1001_ScanResult.SSIDLength;
    Str := '                                                ';
    for J := 0 to Len - 1 do Str[J] := Net_Wireless_MCW1001_ScanResult.SSID[J];
    Rtrim(Str);
    Uart1_Write_text(Str);
    Uart1_Write_text(' ');
    bytetostr(Net_Wireless_MCW1001_ScanResult.Channel, Str);
    uart1_write_text_CRLF(str);
  end;
end;

begin
  InitMcu;

  Uart1_write_text_CRLF('');
  Uart1_Write_Text_CRLF('Started WiFi HTTP Client');

  Net_Wireless_MCW1001_HwReset();

  InitNetwork;
  T1Ie_bit := 1; // enable timer1

  init_wifi;
  Scan;
  ConnectToAP;
  TCP_Setup;
  PutConstString(@initrequest);
  while true do
  begin
    //CheckToSend;
    CheckTcpReceive;
  end;
end.
The answer I get now is (you will have to ignore the "--> received xx <--" lines and its preceding and following empty lines) :
.........
Init Wifi Success!
Scanresults: 1
xxxxxx 1
Connecting to AP, takes a while...
Connecting to AP success
Wifi status: 1
Socket is OK
Handle: 0
Bind is OK
Bindresult: 0
TCP_Connect response: 254
TCP_Connect response: 0
TCP_Connect Success


--> Received: 255 <--

HTTP/1.1 200 OK
Cache-Control: no-cache
Cache-Control: no-cache, no-store, must-revalidate
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Date: Fri, 28 Apr 2023 17:33:09 GMT
Expires: -1
Pragma: no-cache
K

--> Received: 255 <--

eep-Alive: timeout=60, max=300
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; connect-src 'self'; font-src 'self'; frame-src https://service.avm.de https://help.

--> Received: 255 <--

avm.de https://www.avm.de https://avm.de https://assets.avm.de https://clickonce.avm.de http://clickonce.avm.de http://download.avm.de https://download.avm.de 'self'; img-src 'self' https://tv.avm.de https://help.avm.de/images/ http://help.avm.de/images/

--> Received: 255 <--

data:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; media-src 'self'

1b85
<!DOCTYPE html><html lang="en"><head><meta http-equiv=content-type content="text/html; charset=utf-8" /><meta http-equiv="Cac

--> Received: 255 <--

he-Control" content="private, no-transform" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="format-detection" content="telephone=no" /><meta http-equiv="x-rim-auto-match" content="none" /><meta name="viewport" content="width=devic

--> Received: 255 <--

e-width, initial-scale=1.0, user-scalable=yes, minimal-ui" /><meta name="mobile-web-app-capable" content="yes" /><meta name="apple-mobile-web-app-capable" content="yes" /><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />

--> Received: 255 <--

<meta http-equiv="cleartype" content="on"><link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" /><link rel="apple-touch-icon" href="/css/rd/logos/logo_fritzDiamond.png" /><link rel="apple-touch-startup-image" href="/css/rd/logos/logo_frit

--> Received: 255 <--

zDiamond.png"><style>@font-face {font-family: 'AVM';src: url('/css/rd/fonts/metaWebProBold.woff') format('woff');font-weight: bold;}@font-face {font-family: 'Source Sans Pro';font-style: normal;font-weight: 400;src: url('/css/rd/fonts/sourcesan

--> Received: 255 <--

spro.woff') format('woff');}@font-face {font-family: 'Source Sans Pro';font-style: normal;font-weight: 600;src: url('/css/rd/fonts/sourcesansproBold.woff') format('woff');}@font-face {font-family: 'Hack';font-style: normal;font-weight: 400;src

--> Received: 255 <--

: url('/css/rd/fonts/hack.woff') format('woff');}html, input, textarea, keygen, select, button {font-family: 'Source Sans Pro', Arial, sans-serif;font-size: 100%;}.blue_bar_title,.logoArea {font-family: 'AVM', 'Source Sans Pro', Arial, sans-serif;

--> Received: 255 <--

}.monospace {font-family: 'Hack', monospace;}</style><link rel='stylesheet' type='text/css' href="/css/rd/login.css"/><title>FRITZ!Box</title></head><body><script>var gNbc = false,config = {"gu_type":"release","GUI_IS_POWERLINE":false,"GUI_

--> Received: 255 <--

IS_REPEATER":false,"isDebug":false,"language":"en"};</script><script src="/js/browser.js"></script><script src="/js/avmcore.js?lang=en"></script><script src="/js/directPageCall.js"></script><script src="/js/vendor.js"></script><script src="/js/box-l

--> Received: 255 <--

ogin.js"></script><script src="/js/login.js?lang=en"></script><script>var data = {"firstTenMin":false,"challenge":"2$60000$d2a63f0de91a5349c7ec4b5fd7c280da$6000$d846c7c40c9b5f127edbb948878da6c3","blockTime":0,"pageTitle":"Welcome to your FRITZ!Box","la

--> Received: 255 <--

stPage":"","firstWizDone":true,"loginReason":0,"username":"","abortConfig":false,"facTitle":"FRITZ!Box Factory Settings","falseUsername":false,"showFactoryPasswordHint":true,"txt":{"forgotPassword":"Forgot your password?","loginWithPassword":"You can also

--> Received: 255 <--

log in %1%showPasswordLink%with the FRITZ!Box password only%\/1%showPasswordLink%.","facOnAllowedComp":"You start to restore the factory settings from a computer for which no limitations for internet use are defined.","pleaseChoose":"Please select...","l

--> Received: 255 <--

oginAgainUserMailPass":"Please log in with your username or email address and your password.","facNotSet":"The FRITZ!Box was not reset to its factory settings.","loginLinkMailPossibleMyF":"If your FRITZ!Box is registered with MyFRITZ!, the access link is

--> Received: 255 <--

also sent to the email address to which the MyFRITZ! account is registered.","notAuthorized":"You are currently logged in as user %1%Name%. This user is not authorized to access the FRITZ!Box contents you requested.","autoLogoutLoginAgain":"You've been lo

--> Received: 255 <--

gged out automatically; please log back in.","pushNotWorking":"Push service isn't working?","sendLoginLink":"Send access link","pushLoginRestartExplain":"For security reasons, login with your FRITZ!Box is permitted only during a prescribed period. This pe

--> Received: 255 <--

riod has elapsed.","loginAgainUserPass":"Please log in with your username and your password.","waitMore":"Please wait %1 seconds.","facNotAllowed":"The factory settings could not be restored because this computer does not have the necessary rights.","push

--> Received: 255 <--

LoginRestartBtn":"Start login","waitOne":"Please wait 1 second.","loginWithAnotherUser":"You can also %1%showUsersLink%log in with your username and password%\/1%showUsersLink%.","chooseUsername":"Please enter a username.","sendPushServiceMail":"Send push

--> Received: 255 <--

service mail","facLoseSettings":"Please note that resetting the box will overwrite all of your settings!","mistypedOrNotAuthorized":"Did you make a typing error, or do you not have the right to access this area?","pushLoginRestartRequest":"Please restart

--> Received: 255 <--

the login procedure.","back":"Back","defaultUserHint":"Automatically configured user. You can log in with the FRITZ!Box password.","login":"Log In","autoLogoutTimeout":"You were logged out automatically because no activity has been registered for some ti

--> Received: 255 <--

me.","loginMailSent":"The email with the data for accessing the user interface has been sent.","waitTryAgain":"Please log back in again.","facDisconnectPower":"Disconnect FRITZ!Box from the power mains for at least one minute. After another minute you can

--> Received: 255 <--

open the user interface again. Then click on \"To Overview\".","caution":"Attention","facRepeat":"The factory settings can be restored again.","facNotAllowedOr10Min":"You are not authorized to perform this action, or your FRITZ!Box has been in operation

--> Received: 255 <--

for longer than 10 minutes.","pushBtnWelcome":"Please briefly push any button on your FRITZ!Box to log in.","user":"Username","loginFailed":"Login failed.","choose":"OK","pass":"Password","hint_headline":"Note:","setFacDefaults":"Restore Factory Settings

--> Received: 255 <--

","boxPassword":"FRITZ!Box password","loginBoxPassword":"Please log in using your password.","loginAgainPass":"Please log in using your password.","tooManyLogins":"Too many sessions have been started simultaneously.","pushNeedsWan":"To send a push service

--> Received: 255 <--

mail your FRITZ!Box needs an active internet connection.","loginLinkMailPossible":"If you forgot your password for the user interface, you can have an access link sent as a push service mail.","facFailed":"Restoring the factory settings failed."},"cutPow

--> Received: 255 <--

erTxt":"Disconnect the FRITZ!Box from the power mains for at least one minute, and then return to this page once your FRITZ!Box has been restarted.","facWhatNextTxt":"After the reset you will be automatically redirected to the FRITZ!Box \"Overview\" page.

--> Received: 255 <--

","facPationsTxt":"It can take up to 5 minutes before the FRITZ!Box can be reached again. Please be patient!","showUser":true,"ifSetFacTxt":"If you have forgotten your password, you cannot open the user interface again until the factory settings have bee

--> Received: 255 <--

n restored to the FRITZ!Box.","fallbackRedirectUrl":"http:\/\/192.168.178.1\/","facIsSetTxt":"The FRITZ!Box factory settings are restored and then the system will be rebooted. All connections will be interrupted briefly.","logoutTxt":"\"You've logged out

--> Received: 255 <--

successfully from the FRITZ!Box.\"","bluBarTitle":"FRITZ!Box 7430","changedPassTxt":"\"The password has been changed.\"","pushBtnLogin":false,"activeUsers":[{"value":"fritz5352","text":"fritz5352","UID":"boxuser86"}],"fromInternet":false,"pushmailEnabled"

--> Received: 255 <--

:true,"sid":"0000000000000000"}
103
;if (gNbc) {data.nbc = true;}function localInit() {"use strict";window.history.replaceState({}, '', '/');html.blueBarHead({"type": "login",title: data.bluBarTitle,parent: document.body});login.init(data);

--> Received: 49 <--

}localInit();</script></body></html>
0
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: HTTP client with WIFI plus click [Solved]

#5 Post by Dany » 15 May 2023 16:52

Hi, the final, working, project can be found here: https://libstock.mikroe.com/projects/vi ... ttp-client.
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Post Reply

Return to “Development Boards”