Programming The ESP32 Using Arduino - A Web Client
Written by Harry Fairhead   
Monday, 16 December 2024
Article Index
Programming The ESP32 Using Arduino - A Web Client
WiFi Scan
The Complete Program

WiFi Scan

The scanNetworks method can be used to survey what access points are available. It returns the number of APs available. This in itself isn’t of much use, but behind the scenes it fills in a table of values that provide more information about each AP. This table can be accessed using the usual information functions by passing an integer signifying the AP that the data is needed for.

For example:

void setup() {
  Serial.begin(9600);
  int nNet = WiFi.scanNetworks();
  Serial.println(nNet);
  for (int i = 0; i < nNet; i++) {
    Serial.printf("ssid %s  rssi %d channel 
%d encryption %d\n", WiFi.SSID(i), WiFi.RSSI(i),WiFi.channel(i), WiFi.encryptionType(i)); } Serial.println("Scan complete"); };

This will print the SSID, RSSI and encryption type for each of the detected networks. The scanNetworks method blocks until the scan is complete.

The ESP32 adds some additional features to the scan including an asynchronous version – which of course only works on the ESP32. In this case the scanNetworks function is:

int16_t scanNetworks(bool async = false,
bool show_hidden = false, bool passive = false, uint32_t max_ms_per_chan = 300, uint8_t channel = 0)

The most important is the async parameter which, if set to true, causes the scan to be performed in the background. This returns at once and you can check on the progress using:

int16_t scanComplete()

which returns the number of networks acquired. If it returns a negative value then it is still scanning or an error has occurred. You can test for the error using WIFI_SCAN_FAILED.

The results of the scan can be accessed in the same way as for the synchronous scan:

void setup() {
  Serial.begin(9600);
  WiFi.scanNetworks(true); 
};
void loop() {
  delay(1000);
  int16_t nNet = WiFi.scanComplete();
  if (nNet  >= 0) {
    for (int i = 0; i < nNet; i++) {
      Serial.printf("ssid %s  rssi %d channel %d
encryption %d\n", WiFi.SSID(i), WiFi.RSSI(i), WiFi.channel(i), WiFi.encryptionType(i)); } } WiFi.scanDelete(); }

There is also an alternative way of getting the data:

bool getNetworkInfo(uint8_t networkItem, String &ssid, 
    uint8_t &encryptionType, int32_t &RSSI, 
      uint8_t* &BSSID, int32_t &channel)

which simply loads the data into the variables indicated by the pointers.

ESP32CArduino180

A Web Client

Now that we have a WiFi connection we can start using it. The lowest-level way of making a network connection is to use sockets. This is a standard and very flexible way of making connections using a range of different protocols, however, in practice, most connections are TCP/IP which is used by the internet and the web in particular. You can use sockets if you want to, but this isn’t part of the Arduino library. Instead you can make use of the WiFiClient class to implement a client TCP/IP socket without having to delve into how sockets work.

To create a client you simply create an instance of WiFiClient:

WiFiClient client;

and then use its connect method to connect to a server either via its IP address or its URL. For example:

client.connect("www.example.com", 80);

or:

client.connect("93.184.215.14", 80);

The second parameter is the port to use to connect and, for web pages using HTTP, this is usually port 80.

As long as there is no error, the method returns true if the connection is good, we can start to send and receive data.

But what data? The answer is that it all depends on the protocol you are using. There is nothing about a connection that tells you what to send. It is a completely general I/O mechanism using TCP/IP to transport data. You can send anything, but if you don't send what the server is expecting, you won’t get very far.

The web uses the HTTP protocol and this is essentially a set of text headers that tell the server what to do, and a set of headers that the server sends back to tell you what it has done.

The most basic transaction the client can have with the server is to send a GET request for the server to send a particular file.

This means that the simplest set of headers we can send the server is:

GET /index.html HTTP/1.1
HOST:example.com

An HTTP request always ends with a blank line. If you don't send the blank line then you will get no response from most servers. In addition the HOST header has to have the domain name with no additional syntax - no slashes and no http: or similar.

With the headers defined we can send our first HTTP request using the println method of the client class:

client.println("GET /index.html HTTP/1.1");

client.println("HOST:example.com");

client.println();

The server receives the HTTP request and should respond by sending the data corresponding to the file specified, i.e. index.html. We can read the response just as if the client was a stream:

void loop() {
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }
}

You can make this more complicated by checking the number of bytes read and reading more if the buffer is full, but this is a simple and direct way to get the HTML.

 

In fact, you get more than the HTML as you get the entire HTTP response including the response headers:

HTTP/1.1 200 OK
Accept-Ranges: bytes
Age: 343832
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Mon, 18 Nov 2024 17:54:20 GMT
Etag: "3147526947+gzip"
Expires: Mon, 25 Nov 2024 17:54:20 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECAcc (nyd/D169)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1256
<!doctype html>
<html>

and so on...

Notice the blank line marking the end of the header and signaling that the data payload follows.



Last Updated ( Monday, 16 December 2024 )