How to set up an Access Point, and what it is good for
This commit is contained in:
parent
9ff331ba66
commit
49f0510ce4
168
src/main.cpp
168
src/main.cpp
@ -1,50 +1,154 @@
|
||||
//--------------------------------------------------------------------------------------------------------------------------//
|
||||
// Handling Interrupts correctly
|
||||
// Setting up an Access Point hosted by the ESP32
|
||||
//--------------------------------------------------------------------------------------------------------------------------//
|
||||
|
||||
// What are Interrupts? //
|
||||
// You can see them as certain parts of a programm reacting to a condition at ANY time and place your programm is currently in.
|
||||
// You use them to time reads for example, or for signals, etc etc.
|
||||
// What is the difference between an Access Point and using the ESP as a client? //
|
||||
// Well, there's a big difference as to how either work, and what is needed. As an Access Point, you can create your own little "network" hosted
|
||||
// over the small WLAN module on the developing board. That let's you access a website on the ESP for example, without
|
||||
// having to go over any of your internet provider's servers since it's purely local.
|
||||
// When hosting an Access Point, you CANNOT log into another Wlan network. Clients (for example your phone) can log into the one on the ESP though.
|
||||
// If you want to use an async Webserver, that works better with the use of a router inbetween, and has more advantages all in all.
|
||||
// If no internet connection is required and it's for little displayment, a local Access Point should be enough.
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// Load Wifi library //
|
||||
#include <WiFi.h>
|
||||
|
||||
// Set your network credentials (you are entirely free to choose anything) //
|
||||
const char* _ssid = "ESP32-Access-Point"; // for example
|
||||
const char* _password = "1234IamAPassword"; // that's a bad example, but you get the gist
|
||||
|
||||
// Set up instance and the right port (default: 80) //
|
||||
WiFiServer server(80);
|
||||
|
||||
// String to save the http adress in //
|
||||
String _http = "";
|
||||
|
||||
// State variable for the example following in the loop() function later //
|
||||
String _output_state = "off";
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Initializing the timer //
|
||||
void IRAM_ATTR onTimer();
|
||||
Serial.println("Setting up access point...");
|
||||
WiFi.softAP(_ssid, _password);
|
||||
IPAddress _IP = WiFi.softAPIP(); // You can see what is hosted on the ESP over this IP address.
|
||||
Serial.print("AP IP Address: ");
|
||||
Serial.println(_IP);
|
||||
|
||||
hw_timer_t *My_timer = 0;
|
||||
My_timer = timerBegin(0, 80, true);
|
||||
timerAttachInterrupt(My_timer, &onTimer, true);
|
||||
timerAlarmWrite(My_timer, 5000, true);
|
||||
timerAlarmEnable(My_timer);
|
||||
|
||||
// This is crutial and has to be in the setup.
|
||||
// You can change the frequency as to when it gets called (Check it out online), as well as the reason.
|
||||
|
||||
// You can attach a timer to a Pin for example as well.
|
||||
// That would look something like this:
|
||||
//
|
||||
// pinMode(SWITCH_PIN, INPUT_PULLUP);
|
||||
// attachInterrupt(digitalPinToInterrupt(SWITCH_PIN), switchChanged, CHANGE);
|
||||
// But it's not necessary if you're using Interrupts as a timer.
|
||||
server.begin(); // starts WiFi server.
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Listen for any incoming clients, you can also create a thread extra for this if little processing power is needed //
|
||||
WiFiClient _client = server.available();
|
||||
// If that is the case, make sure to keep the service running. It should not be stopped or interrupted at all if the programm is still running,
|
||||
// I'd advice to use an exeption / interrupt that is listening in on whether or not a new client or http request has been received.
|
||||
// Be careful with that in general if you try it.
|
||||
|
||||
}
|
||||
|
||||
// Handling the function //
|
||||
void IRAM_ATTR onTimer()
|
||||
if(_client)
|
||||
{
|
||||
// This function is called when the interrupt has been triggered.
|
||||
String _current_line = "";
|
||||
while(_client.connected()) // As long as the client is connected...
|
||||
{
|
||||
if(_client.available()) // Checks whether or not there is bites to read from.
|
||||
{
|
||||
char _c = _client.read(); // reads a single bite.
|
||||
_http += _c; // assembling the full http request one by one.
|
||||
|
||||
// Keep your operations in here as SIMPLE as possible, and as quick as possible.
|
||||
// DO NOT do heavy processing on this threat, or perform long lasting operations.
|
||||
// ^ That includes any sort of printing or writing to a file for example.
|
||||
// Also refrain from using while(1) AT ALL COSTS. Short lasting while loops are fine, but also make sure they don't take too long to break out again.
|
||||
if(_c != 10) // Listen in for LF (new line / line feat) since that is
|
||||
// a signal for the end of the request.
|
||||
// (Side note: Using '\n' here should technicall work here, but can create some errors.)
|
||||
// (Use 10 (ASCII) instead to avoid any misleading errors.)
|
||||
{
|
||||
// Send a response here, since every request needs a response.
|
||||
// If something went wrong, be sure to send an error message instead of nothing.
|
||||
|
||||
// Replying: //
|
||||
if(_current_line.length() == 0)
|
||||
{
|
||||
// HTTP headers always start a certain way. So be sure to keep the following format.
|
||||
_client.println("HTTP/1.1 200 OK");
|
||||
_client.println("Content-type:text/html");
|
||||
_client.println("Connection: close");
|
||||
_client.println();
|
||||
// And there you go, a correct response that a client can work with!
|
||||
|
||||
// Now you can technically compute whatever changes the client might have requested,
|
||||
// whether that was a press of a button or a press on a link. Any action needs to be responded to,
|
||||
// or else one might end up in the void of white like a blank page, or nothing happens.
|
||||
// The following is an example of how you would process requests with a html button.
|
||||
|
||||
// NOTE! This is html code written inside a C/C++ code. It's far from optional, and SPIFFS is therefor recommended if a
|
||||
// seperate html & css file is prefered. You can read about that in the tutorial branch to the Async Server.
|
||||
// For now, this is purely for demonstration.
|
||||
|
||||
// Handling the change of the example button //
|
||||
if (_http.indexOf("GET Button on") >= 0)
|
||||
{
|
||||
Serial.println("Button turned on");
|
||||
_output_state = "on";
|
||||
// digitalWrite(PIN, HIGH); // == how you would pull a Pin up when the button activates.
|
||||
}
|
||||
else if (_http.indexOf("GET Button off") >= 0)
|
||||
{
|
||||
Serial.println("Button turned off");
|
||||
_output_state = "off";
|
||||
// digitalWrite(PIN, LOW); // again for example.
|
||||
}
|
||||
|
||||
// That is basically it for now regarding simple interrupts.
|
||||
// It's useful regarding sending data only like every 5 minutes, or every 10 milliseconds for example. Use it carefully, and happy coding. :D
|
||||
// Displaying the site //
|
||||
_client.println("<!DOCTYPE html><html>");
|
||||
_client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
|
||||
_client.println("<link rel=\"icon\" href=\"data:,\">");
|
||||
|
||||
// Set up a button //
|
||||
_client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
|
||||
_client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
|
||||
_client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
|
||||
_client.println("</style></head>"); // closes the style tag.
|
||||
|
||||
if (_output_state=="off")
|
||||
{
|
||||
_client.println("<p><a href=\"Button on\"><button class=\"button\">ON</button></a></p>");
|
||||
}
|
||||
else
|
||||
{
|
||||
_client.println("<p><a href=\"Button off\"><button class=\"button button2\">OFF</button></a></p>");
|
||||
}
|
||||
|
||||
// End the HTTP response with a LF as well //
|
||||
_client.println();
|
||||
break;
|
||||
}
|
||||
else // received a LF, clear the current line for input.
|
||||
{
|
||||
_current_line = "";
|
||||
}
|
||||
} // end of if()
|
||||
else if(_c != 13) // Handles the exeption for if you got anything but a carriage return.
|
||||
// NOTE! Technically, '\r' should also work, but like '\n', it can cause issues.
|
||||
// (Once more use 13 (ASCII) instead)
|
||||
{
|
||||
_current_line += _c;
|
||||
}
|
||||
} // end of if()
|
||||
} // end of while()
|
||||
|
||||
// Clear the request variable for later use //
|
||||
_http = "";
|
||||
|
||||
// Close the connection to the client //
|
||||
_client.stop();
|
||||
Serial.println("Client disconnected.");
|
||||
Serial.println();
|
||||
|
||||
// For every time the loop repeats, a new client and a new http request is being processed.
|
||||
}
|
||||
}
|
||||
|
||||
// As said, the example is a tedious an impractical way to host reactive html code.
|
||||
// Yet, it's enough for simple and fast displaying of values over a local WiFi Webserver.
|
||||
|
||||
// Still, since it needs an entire thread to run, it's far from the ideal way.
|
Loading…
Reference in New Issue
Block a user