Mirror of espurna firmware for wireless switches and more
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
4.4 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. /*
  2. MDNS MODULE
  3. Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. // -----------------------------------------------------------------------------
  6. // mDNS Server
  7. // -----------------------------------------------------------------------------
  8. #include "espurna.h"
  9. #if MDNS_SERVER_SUPPORT
  10. #include "mdns.h"
  11. #include "telnet.h"
  12. #include "utils.h"
  13. #include "web.h"
  14. #include <ESP8266mDNS.h>
  15. // -----------------------------------------------------------------------------
  16. namespace mdns {
  17. namespace {
  18. void addServices() {
  19. #if WEB_SUPPORT
  20. MDNS.addService("http", "tcp", webPort());
  21. #endif
  22. #if TELNET_SUPPORT
  23. MDNS.addService("telnet", "tcp", telnetPort());
  24. #endif
  25. #if OTA_ARDUINOOTA_SUPPORT
  26. // MDNS implementation has its weird way of accessing strings;
  27. // can't pass `String`s directly and must use a char pointer
  28. // to RAM so it could copy it for internal use via `strcpy`
  29. // Since all we use here is build data exposed with `StringView`s,
  30. // force everything in RAM first to avoid a runtime exception.
  31. if (MDNS.enableArduino(OTA_PORT, systemPassword().length() > 0)) {
  32. const auto app = buildApp();
  33. MDNS.addServiceTxt("arduino", "tcp",
  34. "app_name", String(app.name).c_str());
  35. MDNS.addServiceTxt("arduino", "tcp",
  36. "app_version", String(app.version).c_str());
  37. MDNS.addServiceTxt("arduino", "tcp",
  38. "build_date", String(app.build_time).c_str());
  39. MDNS.addServiceTxt("arduino", "tcp",
  40. "mac", String(systemChipId()).c_str());
  41. MDNS.addServiceTxt("arduino", "tcp",
  42. "target_board", String(systemDevice()).c_str());
  43. MDNS.addServiceTxt("arduino", "tcp", "mem_size",
  44. String(static_cast<int>(ESP.getFlashChipRealSize() / 1024), 10));
  45. MDNS.addServiceTxt("arduino", "tcp", "sdk_size",
  46. String(static_cast<int>(ESP.getFlashChipSize() / 1024), 10));
  47. MDNS.addServiceTxt("arduino", "tcp", "free_space",
  48. String(static_cast<int>(ESP.getFreeSketchSpace() / 1024), 10));
  49. }
  50. #endif
  51. }
  52. void start() {
  53. const auto hostname = systemHostname();
  54. if (MDNS.begin(hostname)) {
  55. DEBUG_MSG_P(PSTR("[MDNS] Started with hostname %s\n"), hostname.c_str());
  56. addServices();
  57. espurnaRegisterLoop([]() {
  58. MDNS.update();
  59. });
  60. return;
  61. }
  62. DEBUG_MSG_P(PSTR("[MDNS] ERROR\n"));
  63. }
  64. } // namespace
  65. } // namespace mdsn
  66. // As of right now, this needs to be request -> response operation in the same block,
  67. // so we don't end up using someone else's query results.
  68. // `queryService()` 3rd arg is timeout, by default it blocks for MDNS_QUERYSERVICES_WAIT_TIME (1000)
  69. // TODO: esp8266 allows async pyzeroconf-like API to have this running independently.
  70. // In case something other than MQTT needs this, consider extending the API
  71. // (and notice that RTOS SDK alternative would need to use mdns_query_* ESP-IDF API)
  72. // TODO: both implementations also have separate queries for A and AAAA records :/
  73. bool mdnsServiceQuery(const String& service, const String& protocol, MdnsServerQueryCallback callback) {
  74. bool result { false };
  75. auto found = MDNS.queryService(service, protocol);
  76. for (decltype(found) n = 0; n < found; ++n) {
  77. if (callback(MDNS.IP(n).toString(), MDNS.port(n))) {
  78. result = true;
  79. break;
  80. }
  81. }
  82. MDNS.removeQuery();
  83. return result;
  84. }
  85. bool mdnsRunning() {
  86. return MDNS.isRunning();
  87. }
  88. void mdnsServerSetup() {
  89. // 2.7.x and older require MDNS.begin() when interface is UP
  90. // issue tracker suggest doing begin() for each mode change, but...
  91. // this does seem to imply pairing it with end() (aka close()),
  92. // which will completely reset the MDNS object and require a setup once again.
  93. // this does not seem to work reliably :/ only support STA for the time being
  94. // 3.0.0 and newer only need to do MDNS.begin() once at setup()
  95. // however, note that without begin() call it will immediatly crash b/c
  96. // there are no sanity checks if it was actually called
  97. #if defined(ARDUINO_ESP8266_RELEASE_2_7_2) \
  98. || defined(ARDUINO_ESP8266_RELEASE_2_7_3) \
  99. || defined(ARDUINO_ESP8266_RELEASE_2_7_4)
  100. wifiRegister([](espurna::wifi::Event event) {
  101. if ((event == espurna::wifi::Event::StationConnected) && !MDNS.isRunning()) {
  102. mdns::start();
  103. }
  104. });
  105. #else
  106. mdns::start();
  107. #endif
  108. }
  109. #endif // MDNS_SERVER_SUPPORT