mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-12 01:53:07 +03:00
LEAmDNS - Multicast DNS Responder (#5442)
* LEAmDNS Responder (II) Created a new branch to solve commit conflicts with recent changes to ESP8266mDNSResponder.cpp by d-a-v. * Removed millis() roll-over issues * fix LEA-mDNS * astyle on lea-mdns examples * add compatibility with lwIP-v1 * ditto * use strncasecmp instead of lwip's strnicmp from lwIP-v2 (thanks @devyte) * ditto * fixes * Update mDNS_Clock.ino unindent * Update mDNS_ServiceMonitor.ino unindent * Update LEAmDNS.h Add setInstanceName() forwarder for compat * Disable DEBUG_ESP_MDNS_RESPONDER by default * [Fixed] Debug output line DEBUG_OUTPUT needs to go inside DEBUG_EX_ function otherwise throw error if DEBUG_ESP_MDNS_RESPONDER is not defined
This commit is contained in:
334
libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino
Normal file
334
libraries/ESP8266mDNS/examples/LEAmDNS/mDNS_Clock/mDNS_Clock.ino
Normal file
@ -0,0 +1,334 @@
|
||||
/*
|
||||
ESP8266 mDNS responder clock
|
||||
|
||||
This example demonstrates two features of the LEA MDNSResponder:
|
||||
1. The host and service domain negotiation process that ensures
|
||||
the uniqueness of the finally choosen host and service domain name.
|
||||
2. The dynamic MDNS service TXT feature
|
||||
|
||||
A 'clock' service in announced via the MDNS responder and the current
|
||||
time is set as a TXT item (eg. 'curtime=Mon Oct 15 19:54:35 2018').
|
||||
The time value is updated every second!
|
||||
|
||||
The ESP is initially announced to clients as 'esp8266.local', if this host domain
|
||||
is already used in the local network, another host domain is negociated. Keep an
|
||||
eye to the serial output to learn the final host domain for the clock service.
|
||||
The service itself is is announced as 'host domain'._espclk._tcp.local.
|
||||
As the service uses port 80, a very simple HTTP server is installed also to deliver
|
||||
a small web page containing a greeting and the current time (not updated).
|
||||
The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example.
|
||||
Point your browser to 'host domain'.local to see this web page.
|
||||
|
||||
Instructions:
|
||||
- Update WiFi SSID and password as necessary.
|
||||
- Flash the sketch to the ESP8266 board
|
||||
- Install host software:
|
||||
- For Linux, install Avahi (http://avahi.org/).
|
||||
- For Windows, install Bonjour (http://www.apple.com/support/bonjour/).
|
||||
- For Mac OSX and iOS support is built in through Bonjour already.
|
||||
- Use a MDNS/Bonjour browser like 'Discovery' to find the clock service in your local
|
||||
network and see the current time updates.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
Include the MDNSResponder (the library needs to be included also)
|
||||
As LEA MDNSResponder is experimantal in the ESP8266 environment currently, the
|
||||
legacy MDNSResponder is defaulted in th include file.
|
||||
There are two ways to access LEA MDNSResponder:
|
||||
1. Prepend every declaration and call to global declarations or functions with the namespace, like:
|
||||
'LEAmDNS::MDNSResponder::hMDNSService hMDNSService;'
|
||||
This way is used in the example. But be careful, if the namespace declaration is missing
|
||||
somewhere, the call might go to the legacy implementation...
|
||||
2. Open 'ESP8266mDNS.h' and set LEAmDNS to default.
|
||||
|
||||
*/
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <LEATimeFlag.h>
|
||||
|
||||
/*
|
||||
Global defines and vars
|
||||
*/
|
||||
|
||||
#define TIMEZONE_OFFSET 1 // CET
|
||||
#define DST_OFFSET 1 // CEST
|
||||
#define UPDATE_CYCLE (1 * 1000) // every second
|
||||
|
||||
#define SERVICE_PORT 80 // HTTP port
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
char* pcHostDomain = 0; // Negociated host domain
|
||||
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
|
||||
LEAmDNS::MDNSResponder::hMDNSService hMDNSService = 0; // The handle of the clock service in the MDNS responder
|
||||
|
||||
// TCP server at port 'SERVICE_PORT' will respond to HTTP requests
|
||||
WiFiServer server(SERVICE_PORT);
|
||||
|
||||
|
||||
/*
|
||||
getTimeString
|
||||
*/
|
||||
const char* getTimeString(void) {
|
||||
|
||||
static char acTimeString[32];
|
||||
time_t now = time(nullptr);
|
||||
ctime_r(&now, acTimeString);
|
||||
size_t stLength;
|
||||
while (((stLength = os_strlen(acTimeString))) &&
|
||||
('\n' == acTimeString[stLength - 1])) {
|
||||
acTimeString[stLength - 1] = 0; // Remove trailing line break...
|
||||
}
|
||||
return acTimeString;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setClock
|
||||
|
||||
Set time via NTP
|
||||
*/
|
||||
void setClock(void) {
|
||||
configTime((TIMEZONE_OFFSET * 3600), (DST_OFFSET * 3600), "pool.ntp.org", "time.nist.gov", "time.windows.com");
|
||||
|
||||
Serial.print("Waiting for NTP time sync: ");
|
||||
time_t now = time(nullptr); // Secs since 01.01.1970 (when uninitalized starts with (8 * 3600 = 28800)
|
||||
while (now < 8 * 3600 * 2) { // Wait for realistic value
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
now = time(nullptr);
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.printf("Current time: %s\n", getTimeString());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setStationHostname
|
||||
*/
|
||||
bool setStationHostname(const char* p_pcHostname) {
|
||||
|
||||
if (p_pcHostname) {
|
||||
WiFi.hostname(p_pcHostname);
|
||||
Serial.printf("setDeviceHostname: Station hostname is set to '%s'\n", p_pcHostname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MDNSDynamicServiceTxtCallback
|
||||
|
||||
Add a dynamic MDNS TXT item 'ct' to the clock service.
|
||||
The callback function is called every time, the TXT items for the clock service
|
||||
are needed.
|
||||
This can be triggered by calling MDNS.announce().
|
||||
|
||||
*/
|
||||
bool MDNSDynamicServiceTxtCallback(LEAmDNS::MDNSResponder* p_pMDNSResponder,
|
||||
const LEAmDNS::MDNSResponder::hMDNSService p_hService,
|
||||
void* p_pUserdata) {
|
||||
Serial.println("MDNSDynamicServiceTxtCallback");
|
||||
(void) p_pUserdata;
|
||||
|
||||
if ((p_pMDNSResponder) &&
|
||||
(hMDNSService == p_hService)) {
|
||||
Serial.printf("Updating curtime TXT item to: %s\n", getTimeString());
|
||||
p_pMDNSResponder->addDynamicServiceTxt(p_hService, "curtime", getTimeString());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MDNSProbeResultCallback
|
||||
|
||||
Probe result callback for the host domain.
|
||||
If the domain is free, the host domain is set and the clock service is
|
||||
added.
|
||||
If the domain is already used, a new name is created and the probing is
|
||||
restarted via p_pMDNSResponder->setHostname().
|
||||
|
||||
*/
|
||||
bool MDNSProbeResultCallback(LEAmDNS::MDNSResponder* p_pMDNSResponder,
|
||||
const char* p_pcDomainName,
|
||||
const LEAmDNS::MDNSResponder::hMDNSService p_hService,
|
||||
bool p_bProbeResult,
|
||||
void* p_pUserdata) {
|
||||
Serial.println("MDNSProbeResultCallback");
|
||||
(void) p_pUserdata;
|
||||
|
||||
if ((p_pMDNSResponder) &&
|
||||
(0 == p_hService)) { // Called for host domain
|
||||
Serial.printf("MDNSProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName, (p_bProbeResult ? "free" : "already USED!"));
|
||||
if (true == p_bProbeResult) {
|
||||
// Set station hostname
|
||||
setStationHostname(pcHostDomain);
|
||||
|
||||
if (!bHostDomainConfirmed) {
|
||||
// Hostname free -> setup clock service
|
||||
bHostDomainConfirmed = true;
|
||||
|
||||
if (!hMDNSService) {
|
||||
// Add a 'clock.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain
|
||||
hMDNSService = p_pMDNSResponder->addService(0, "espclk", "tcp", SERVICE_PORT);
|
||||
if (hMDNSService) {
|
||||
// Add a simple static MDNS service TXT item
|
||||
p_pMDNSResponder->addServiceTxt(hMDNSService, "port#", SERVICE_PORT);
|
||||
// Set the callback function for dynamic service TXTs
|
||||
p_pMDNSResponder->setDynamicServiceTxtCallback(hMDNSService, MDNSDynamicServiceTxtCallback, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Change hostname, use '-' as divider between base name and index
|
||||
if (LEAmDNS::MDNSResponder::indexDomain(pcHostDomain, "-", 0)) {
|
||||
p_pMDNSResponder->setHostname(pcHostDomain);
|
||||
} else {
|
||||
Serial.println("MDNSProbeResultCallback: FAILED to update hostname!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
handleHTTPClient
|
||||
*/
|
||||
void handleHTTPClient(WiFiClient& client) {
|
||||
Serial.println("");
|
||||
Serial.println("New client");
|
||||
|
||||
// Wait for data from client to become available
|
||||
while (client.connected() && !client.available()) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Read the first line of HTTP request
|
||||
String req = client.readStringUntil('\r');
|
||||
|
||||
// First line of HTTP request looks like "GET /path HTTP/1.1"
|
||||
// Retrieve the "/path" part by finding the spaces
|
||||
int addr_start = req.indexOf(' ');
|
||||
int addr_end = req.indexOf(' ', addr_start + 1);
|
||||
if (addr_start == -1 || addr_end == -1) {
|
||||
Serial.print("Invalid request: ");
|
||||
Serial.println(req);
|
||||
return;
|
||||
}
|
||||
req = req.substring(addr_start + 1, addr_end);
|
||||
Serial.print("Request: ");
|
||||
Serial.println(req);
|
||||
client.flush();
|
||||
|
||||
// Get current time
|
||||
time_t now = time(nullptr);;
|
||||
struct tm timeinfo;
|
||||
gmtime_r(&now, &timeinfo);
|
||||
|
||||
String s;
|
||||
if (req == "/") {
|
||||
IPAddress ip = WiFi.localIP();
|
||||
String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
|
||||
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
|
||||
s += ipStr;
|
||||
// Simple addition of the current time
|
||||
s += "\r\nCurrent time is: ";
|
||||
s += getTimeString();
|
||||
// done :-)
|
||||
s += "</html>\r\n\r\n";
|
||||
Serial.println("Sending 200");
|
||||
} else {
|
||||
s = "HTTP/1.1 404 Not Found\r\n\r\n";
|
||||
Serial.println("Sending 404");
|
||||
}
|
||||
client.print(s);
|
||||
|
||||
Serial.println("Done with client");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup
|
||||
*/
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Connect to WiFi network
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("");
|
||||
|
||||
// Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
// Sync clock
|
||||
setClock();
|
||||
|
||||
// Setup MDNS responder
|
||||
LEAmDNS::MDNS.setProbeResultCallback(MDNSProbeResultCallback, 0);
|
||||
// Init the (currently empty) host domain string with 'esp8266'
|
||||
if ((!LEAmDNS::MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) ||
|
||||
(!LEAmDNS::MDNS.begin(pcHostDomain))) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
while (1) { // STOP
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
Serial.println("MDNS responder started");
|
||||
|
||||
// Start TCP (HTTP) server
|
||||
server.begin();
|
||||
Serial.println("TCP server started");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
loop
|
||||
*/
|
||||
void loop(void) {
|
||||
// Check if a client has connected
|
||||
WiFiClient client = server.available();
|
||||
if (client) {
|
||||
handleHTTPClient(client);
|
||||
}
|
||||
|
||||
// Allow MDNS processing
|
||||
LEAmDNS::MDNS.update();
|
||||
|
||||
// Update time (if needed)
|
||||
//static unsigned long ulNextTimeUpdate = UPDATE_CYCLE;
|
||||
static clsLEATimeFlag timeFlag(UPDATE_CYCLE);
|
||||
if (timeFlag.flagged()/*ulNextTimeUpdate < millis()*/) {
|
||||
|
||||
if (hMDNSService) {
|
||||
// Just trigger a new MDNS announcement, this will lead to a call to
|
||||
// 'MDNSDynamicServiceTxtCallback', which will update the time TXT item
|
||||
LEAmDNS::MDNS.announce();
|
||||
}
|
||||
//ulNextTimeUpdate = (millis() + UPDATE_CYCLE); // Set update 'timer'
|
||||
timeFlag.restart();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,356 @@
|
||||
/*
|
||||
ESP8266 mDNS Responder Service Monitor
|
||||
|
||||
This example demonstrates two features of the LEA MDNSResponder:
|
||||
1. The host and service domain negotiation process that ensures
|
||||
the uniqueness of the finally choosen host and service domain name.
|
||||
2. The dynamic MDNS service lookup/query feature.
|
||||
|
||||
A list of 'HTTP' services in the local network is created and kept up to date.
|
||||
In addition to this, a (very simple) HTTP server is set up on port 80
|
||||
and announced as a service.
|
||||
|
||||
The ESP itself is initially announced to clients as 'esp8266.local', if this host domain
|
||||
is already used in the local network, another host domain is negociated. Keep an
|
||||
eye to the serial output to learn the final host domain for the HTTP service.
|
||||
The service itself is is announced as 'host domain'._http._tcp.local.
|
||||
The HTTP server delivers a short greeting and the current list of other 'HTTP' services (not updated).
|
||||
The web server code is taken nearly 1:1 from the 'mDNS_Web_Server.ino' example.
|
||||
Point your browser to 'host domain'.local to see this web page.
|
||||
|
||||
Instructions:
|
||||
- Update WiFi SSID and password as necessary.
|
||||
- Flash the sketch to the ESP8266 board
|
||||
- Install host software:
|
||||
- For Linux, install Avahi (http://avahi.org/).
|
||||
- For Windows, install Bonjour (http://www.apple.com/support/bonjour/).
|
||||
- For Mac OSX and iOS support is built in through Bonjour already.
|
||||
- Use a browser like 'Safari' to see the page at http://'host domain'.local.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
|
||||
/*
|
||||
Include the MDNSResponder (the library needs to be included also)
|
||||
As LEA MDNSResponder is experimantal in the ESP8266 environment currently, the
|
||||
legacy MDNSResponder is defaulted in th include file.
|
||||
There are two ways to access LEA MDNSResponder:
|
||||
1. Prepend every declaration and call to global declarations or functions with the namespace, like:
|
||||
'LEAmDNS:MDNSResponder::hMDNSService hMDNSService;'
|
||||
This way is used in the example. But be careful, if the namespace declaration is missing
|
||||
somewhere, the call might go to the legacy implementation...
|
||||
2. Open 'ESP8266mDNS.h' and set LEAmDNS to default.
|
||||
|
||||
*/
|
||||
#include <ESP8266mDNS.h>
|
||||
|
||||
/*
|
||||
Global defines and vars
|
||||
*/
|
||||
|
||||
#define SERVICE_PORT 80 // HTTP port
|
||||
|
||||
#ifndef STASSID
|
||||
#define STASSID "your-ssid"
|
||||
#define STAPSK "your-password"
|
||||
#endif
|
||||
|
||||
const char* ssid = STASSID;
|
||||
const char* password = STAPSK;
|
||||
|
||||
char* pcHostDomain = 0; // Negociated host domain
|
||||
bool bHostDomainConfirmed = false; // Flags the confirmation of the host domain
|
||||
LEAmDNS::MDNSResponder::hMDNSService hMDNSService = 0; // The handle of the http service in the MDNS responder
|
||||
LEAmDNS::MDNSResponder::hMDNSServiceQuery hMDNSServiceQuery = 0; // The handle of the 'http.tcp' service query in the MDNS responder
|
||||
|
||||
const String cstrNoHTTPServices = "Currently no 'http.tcp' services in the local network!<br/>";
|
||||
String strHTTPServices = cstrNoHTTPServices;
|
||||
|
||||
// TCP server at port 'SERVICE_PORT' will respond to HTTP requests
|
||||
WiFiServer server(SERVICE_PORT);
|
||||
|
||||
|
||||
/*
|
||||
setStationHostname
|
||||
*/
|
||||
bool setStationHostname(const char* p_pcHostname) {
|
||||
|
||||
if (p_pcHostname) {
|
||||
WiFi.hostname(p_pcHostname);
|
||||
Serial.printf("setStationHostname: Station hostname is set to '%s'\n", p_pcHostname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MDNSServiceQueryCallback
|
||||
*/
|
||||
bool MDNSServiceQueryCallback(LEAmDNS::MDNSResponder* p_pMDNSResponder, // The MDNS responder object
|
||||
const LEAmDNS::MDNSResponder::hMDNSServiceQuery p_hServiceQuery, // Handle to the service query
|
||||
uint32_t p_u32AnswerIndex, // Index of the updated answer
|
||||
uint32_t p_u32ServiceQueryAnswerMask, // Mask for the updated component
|
||||
bool p_bSetContent, // true: Component set, false: component deleted
|
||||
void* p_pUserdata) { // pUserdata; here '0', as none set via 'installServiceQuery'
|
||||
(void) p_pUserdata;
|
||||
Serial.printf("MDNSServiceQueryCallback\n");
|
||||
|
||||
if ((p_pMDNSResponder) &&
|
||||
(hMDNSServiceQuery == p_hServiceQuery)) {
|
||||
|
||||
if (LEAmDNS::MDNSResponder::ServiceQueryAnswerType_ServiceDomain & p_u32ServiceQueryAnswerMask) {
|
||||
Serial.printf("MDNSServiceQueryCallback: Service domain '%s' %s index %u\n",
|
||||
p_pMDNSResponder->answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex),
|
||||
(p_bSetContent ? "added at" : "removed from"),
|
||||
p_u32AnswerIndex);
|
||||
} else if (LEAmDNS::MDNSResponder::ServiceQueryAnswerType_HostDomainAndPort & p_u32ServiceQueryAnswerMask) {
|
||||
if (p_bSetContent) {
|
||||
Serial.printf("MDNSServiceQueryCallback: Host domain and port added/updated for service '%s': %s:%u\n",
|
||||
p_pMDNSResponder->answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex),
|
||||
p_pMDNSResponder->answerHostDomain(p_hServiceQuery, p_u32AnswerIndex),
|
||||
p_pMDNSResponder->answerPort(p_hServiceQuery, p_u32AnswerIndex));
|
||||
} else {
|
||||
Serial.printf("MDNSServiceQueryCallback: Host domain and port removed from service '%s'\n",
|
||||
p_pMDNSResponder->answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex));
|
||||
}
|
||||
} else if (LEAmDNS::MDNSResponder::ServiceQueryAnswerType_IP4Address & p_u32ServiceQueryAnswerMask) {
|
||||
if (p_bSetContent) {
|
||||
Serial.printf("MDNSServiceQueryCallback: IP4 address added/updated for service '%s':\n",
|
||||
p_pMDNSResponder->answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex));
|
||||
for (uint32_t u = 0; u < p_pMDNSResponder->answerIP4AddressCount(p_hServiceQuery, p_u32AnswerIndex); ++u) {
|
||||
Serial.printf("- %s\n", p_pMDNSResponder->answerIP4Address(p_hServiceQuery, p_u32AnswerIndex, u).toString().c_str());
|
||||
}
|
||||
} else {
|
||||
Serial.printf("MDNSServiceQueryCallback: IP4 address removed from service '%s'\n",
|
||||
p_pMDNSResponder->answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex));
|
||||
}
|
||||
} else if (LEAmDNS::MDNSResponder::ServiceQueryAnswerType_Txts & p_u32ServiceQueryAnswerMask) {
|
||||
if (p_bSetContent) {
|
||||
Serial.printf("MDNSServiceQueryCallback: TXT items added/updated for service '%s': %s\n",
|
||||
p_pMDNSResponder->answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex),
|
||||
p_pMDNSResponder->answerTxts(p_hServiceQuery, p_u32AnswerIndex));
|
||||
} else {
|
||||
Serial.printf("MDNSServiceQueryCallback: TXT items removed from service '%s'\n",
|
||||
p_pMDNSResponder->answerServiceDomain(p_hServiceQuery, p_u32AnswerIndex));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create the current list of 'http.tcp' services
|
||||
uint32_t u32Answers = p_pMDNSResponder->answerCount(p_hServiceQuery);
|
||||
if (u32Answers) {
|
||||
strHTTPServices = "";
|
||||
for (uint32_t u = 0; u < u32Answers; ++u) {
|
||||
// Index and service domain
|
||||
strHTTPServices += u;
|
||||
strHTTPServices += ": ";
|
||||
strHTTPServices += p_pMDNSResponder->answerServiceDomain(p_hServiceQuery, u);
|
||||
// Host domain and port
|
||||
if ((p_pMDNSResponder->hasAnswerHostDomain(p_hServiceQuery, u)) &&
|
||||
(p_pMDNSResponder->hasAnswerPort(p_hServiceQuery, u))) {
|
||||
|
||||
strHTTPServices += " at ";
|
||||
strHTTPServices += p_pMDNSResponder->answerHostDomain(p_hServiceQuery, u);
|
||||
strHTTPServices += ":";
|
||||
strHTTPServices += p_pMDNSResponder->answerPort(p_hServiceQuery, u);
|
||||
}
|
||||
// IP4 address
|
||||
if (p_pMDNSResponder->hasAnswerIP4Address(p_hServiceQuery, u)) {
|
||||
strHTTPServices += " IP4: ";
|
||||
for (uint32_t u2 = 0; u2 < p_pMDNSResponder->answerIP4AddressCount(p_hServiceQuery, u); ++u2) {
|
||||
if (0 != u2) {
|
||||
strHTTPServices += ", ";
|
||||
}
|
||||
strHTTPServices += p_pMDNSResponder->answerIP4Address(p_hServiceQuery, u, u2).toString();
|
||||
}
|
||||
}
|
||||
// MDNS TXT items
|
||||
if (p_pMDNSResponder->hasAnswerTxts(p_hServiceQuery, u)) {
|
||||
strHTTPServices += " TXT: ";
|
||||
strHTTPServices += p_pMDNSResponder->answerTxts(p_hServiceQuery, u);
|
||||
}
|
||||
strHTTPServices += "<br/>";
|
||||
}
|
||||
} else {
|
||||
strHTTPServices = cstrNoHTTPServices;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MDNSProbeResultCallback
|
||||
|
||||
Probe result callback for the host domain.
|
||||
If the domain is free, the host domain is set and the http service is
|
||||
added.
|
||||
If the domain is already used, a new name is created and the probing is
|
||||
restarted via p_pMDNSResponder->setHostname().
|
||||
|
||||
*/
|
||||
bool MDNSProbeResultCallback(LEAmDNS::MDNSResponder* p_pMDNSResponder,
|
||||
const char* p_pcDomainName,
|
||||
const LEAmDNS::MDNSResponder::hMDNSService p_hService,
|
||||
bool p_bProbeResult,
|
||||
void* p_pUserdata) {
|
||||
(void) p_pUserdata;
|
||||
|
||||
if ((p_pMDNSResponder) &&
|
||||
(0 == p_hService)) { // Called for host domain
|
||||
|
||||
Serial.printf("MDNSProbeResultCallback: Host domain '%s.local' is %s\n", p_pcDomainName, (p_bProbeResult ? "free" : "already USED!"));
|
||||
|
||||
if (true == p_bProbeResult) {
|
||||
// Set station hostname
|
||||
setStationHostname(pcHostDomain);
|
||||
|
||||
if (!bHostDomainConfirmed) {
|
||||
// Hostname free -> setup clock service
|
||||
bHostDomainConfirmed = true;
|
||||
|
||||
if (!hMDNSService) {
|
||||
// Add a 'http.tcp' service to port 'SERVICE_PORT', using the host domain as instance domain
|
||||
hMDNSService = p_pMDNSResponder->addService(0, "http", "tcp", SERVICE_PORT);
|
||||
if (hMDNSService) {
|
||||
// Add some '_http._tcp' protocol specific MDNS service TXT items
|
||||
// See: http://www.dns-sd.org/txtrecords.html#http
|
||||
p_pMDNSResponder->addServiceTxt(hMDNSService, "user", "");
|
||||
p_pMDNSResponder->addServiceTxt(hMDNSService, "password", "");
|
||||
p_pMDNSResponder->addServiceTxt(hMDNSService, "path", "/");
|
||||
}
|
||||
|
||||
// Install dynamic 'http.tcp' service query
|
||||
if (!hMDNSServiceQuery) {
|
||||
hMDNSServiceQuery = p_pMDNSResponder->installServiceQuery("http", "tcp", MDNSServiceQueryCallback, 0);
|
||||
if (hMDNSServiceQuery) {
|
||||
Serial.printf("MDNSProbeResultCallback: Service query for 'http.tcp' services installed.\n");
|
||||
} else {
|
||||
Serial.printf("MDNSProbeResultCallback: FAILED to install service query for 'http.tcp' services!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Change hostname, use '-' as divider between base name and index
|
||||
if (LEAmDNS::MDNSResponder::indexDomain(pcHostDomain, "-", 0)) {
|
||||
p_pMDNSResponder->setHostname(pcHostDomain);
|
||||
} else {
|
||||
Serial.println("MDNSProbeResultCallback: FAILED to update hostname!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
handleHTTPClient
|
||||
*/
|
||||
void handleHTTPClient(WiFiClient& client) {
|
||||
Serial.println("");
|
||||
Serial.println("New client");
|
||||
|
||||
// Wait for data from client to become available
|
||||
while (client.connected() && !client.available()) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Read the first line of HTTP request
|
||||
String req = client.readStringUntil('\r');
|
||||
|
||||
// First line of HTTP request looks like "GET /path HTTP/1.1"
|
||||
// Retrieve the "/path" part by finding the spaces
|
||||
int addr_start = req.indexOf(' ');
|
||||
int addr_end = req.indexOf(' ', addr_start + 1);
|
||||
if (addr_start == -1 || addr_end == -1) {
|
||||
Serial.print("Invalid request: ");
|
||||
Serial.println(req);
|
||||
return;
|
||||
}
|
||||
req = req.substring(addr_start + 1, addr_end);
|
||||
Serial.print("Request: ");
|
||||
Serial.println(req);
|
||||
client.flush();
|
||||
|
||||
String s;
|
||||
if (req == "/") {
|
||||
IPAddress ip = WiFi.localIP();
|
||||
String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
|
||||
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
|
||||
s += ipStr;
|
||||
// Simple addition of the current time
|
||||
s += "<br/>Local HTTP services:<br/>";
|
||||
s += strHTTPServices;
|
||||
// done :-)
|
||||
s += "</html>\r\n\r\n";
|
||||
Serial.println("Sending 200");
|
||||
} else {
|
||||
s = "HTTP/1.1 404 Not Found\r\n\r\n";
|
||||
Serial.println("Sending 404");
|
||||
}
|
||||
client.print(s);
|
||||
|
||||
Serial.println("Done with client");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup
|
||||
*/
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(false);
|
||||
|
||||
// Connect to WiFi network
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial.println("");
|
||||
|
||||
// Wait for connection
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
// Setup MDNS responder
|
||||
LEAmDNS::MDNS.setProbeResultCallback(MDNSProbeResultCallback, 0);
|
||||
// Init the (currently empty) host domain string with 'esp8266'
|
||||
if ((!LEAmDNS::MDNSResponder::indexDomain(pcHostDomain, 0, "esp8266")) ||
|
||||
(!LEAmDNS::MDNS.begin(pcHostDomain))) {
|
||||
Serial.println("Error setting up MDNS responder!");
|
||||
while (1) { // STOP
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
Serial.println("MDNS responder started");
|
||||
|
||||
// Start TCP (HTTP) server
|
||||
server.begin();
|
||||
Serial.println("TCP server started");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
loop
|
||||
*/
|
||||
void loop(void) {
|
||||
// Check if a client has connected
|
||||
WiFiClient client = server.available();
|
||||
if (client) {
|
||||
handleHTTPClient(client);
|
||||
}
|
||||
|
||||
// Allow MDNS processing
|
||||
LEAmDNS::MDNS.update();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user