mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	[mdns] Support templatable config options for MDNS extra services (#8606)
This commit is contained in:
		| @@ -35,8 +35,8 @@ SERVICE_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_SERVICE): cv.string, | ||||
|         cv.Required(CONF_PROTOCOL): cv.string, | ||||
|         cv.Optional(CONF_PORT, default=0): cv.Any(0, cv.port), | ||||
|         cv.Optional(CONF_TXT, default={}): {cv.string: cv.string}, | ||||
|         cv.Optional(CONF_PORT, default=0): cv.templatable(cv.Any(0, cv.port)), | ||||
|         cv.Optional(CONF_TXT, default={}): {cv.string: cv.templatable(cv.string)}, | ||||
|     } | ||||
| ) | ||||
|  | ||||
| @@ -102,12 +102,18 @@ async def to_code(config): | ||||
|  | ||||
|     for service in config[CONF_SERVICES]: | ||||
|         txt = [ | ||||
|             mdns_txt_record(txt_key, txt_value) | ||||
|             cg.StructInitializer( | ||||
|                 MDNSTXTRecord, | ||||
|                 ("key", txt_key), | ||||
|                 ("value", await cg.templatable(txt_value, [], cg.std_string)), | ||||
|             ) | ||||
|             for txt_key, txt_value in service[CONF_TXT].items() | ||||
|         ] | ||||
|  | ||||
|         exp = mdns_service( | ||||
|             service[CONF_SERVICE], service[CONF_PROTOCOL], service[CONF_PORT], txt | ||||
|             service[CONF_SERVICE], | ||||
|             service[CONF_PROTOCOL], | ||||
|             await cg.templatable(service[CONF_PORT], [], cg.uint16), | ||||
|             txt, | ||||
|         ) | ||||
|  | ||||
|         cg.add(var.add_extra_service(exp)) | ||||
|   | ||||
| @@ -121,9 +121,11 @@ void MDNSComponent::dump_config() { | ||||
|   ESP_LOGCONFIG(TAG, "  Hostname: %s", this->hostname_.c_str()); | ||||
|   ESP_LOGV(TAG, "  Services:"); | ||||
|   for (const auto &service : this->services_) { | ||||
|     ESP_LOGV(TAG, "  - %s, %s, %d", service.service_type.c_str(), service.proto.c_str(), service.port); | ||||
|     ESP_LOGV(TAG, "  - %s, %s, %d", service.service_type.c_str(), service.proto.c_str(), | ||||
|              const_cast<TemplatableValue<uint16_t> &>(service.port).value()); | ||||
|     for (const auto &record : service.txt_records) { | ||||
|       ESP_LOGV(TAG, "    TXT: %s = %s", record.key.c_str(), record.value.c_str()); | ||||
|       ESP_LOGV(TAG, "    TXT: %s = %s", record.key.c_str(), | ||||
|                const_cast<TemplatableValue<std::string> &>(record.value).value().c_str()); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #ifdef USE_MDNS | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include "esphome/core/automation.h" | ||||
| #include "esphome/core/component.h" | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -10,7 +11,7 @@ namespace mdns { | ||||
|  | ||||
| struct MDNSTXTRecord { | ||||
|   std::string key; | ||||
|   std::string value; | ||||
|   TemplatableValue<std::string> value; | ||||
| }; | ||||
|  | ||||
| struct MDNSService { | ||||
| @@ -20,7 +21,7 @@ struct MDNSService { | ||||
|   // second label indicating protocol _including_ underscore character prefix | ||||
|   // as defined in RFC6763 Section 7, like "_tcp" or "_udp" | ||||
|   std::string proto; | ||||
|   uint16_t port; | ||||
|   TemplatableValue<uint16_t> port; | ||||
|   std::vector<MDNSTXTRecord> txt_records; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -31,11 +31,12 @@ void MDNSComponent::setup() { | ||||
|       mdns_txt_item_t it{}; | ||||
|       // dup strings to ensure the pointer is valid even after the record loop | ||||
|       it.key = strdup(record.key.c_str()); | ||||
|       it.value = strdup(record.value.c_str()); | ||||
|       it.value = strdup(const_cast<TemplatableValue<std::string> &>(record.value).value().c_str()); | ||||
|       txt_records.push_back(it); | ||||
|     } | ||||
|     err = mdns_service_add(nullptr, service.service_type.c_str(), service.proto.c_str(), service.port, | ||||
|                            txt_records.data(), txt_records.size()); | ||||
|     uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value(); | ||||
|     err = mdns_service_add(nullptr, service.service_type.c_str(), service.proto.c_str(), port, txt_records.data(), | ||||
|                            txt_records.size()); | ||||
|  | ||||
|     // free records | ||||
|     for (const auto &it : txt_records) { | ||||
|   | ||||
| @@ -29,9 +29,11 @@ void MDNSComponent::setup() { | ||||
|     while (*service_type == '_') { | ||||
|       service_type++; | ||||
|     } | ||||
|     MDNS.addService(service_type, proto, service.port); | ||||
|     uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value(); | ||||
|     MDNS.addService(service_type, proto, port); | ||||
|     for (const auto &record : service.txt_records) { | ||||
|       MDNS.addServiceTxt(service_type, proto, record.key.c_str(), record.value.c_str()); | ||||
|       MDNS.addServiceTxt(service_type, proto, record.key.c_str(), | ||||
|                          const_cast<TemplatableValue<std::string> &>(record.value).value().c_str()); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -29,9 +29,11 @@ void MDNSComponent::setup() { | ||||
|     while (*service_type == '_') { | ||||
|       service_type++; | ||||
|     } | ||||
|     MDNS.addService(service_type, proto, service.port); | ||||
|     uint16_t port_ = const_cast<TemplatableValue<uint16_t> &>(service.port).value(); | ||||
|     MDNS.addService(service_type, proto, port_); | ||||
|     for (const auto &record : service.txt_records) { | ||||
|       MDNS.addServiceTxt(service_type, proto, record.key.c_str(), record.value.c_str()); | ||||
|       MDNS.addServiceTxt(service_type, proto, record.key.c_str(), | ||||
|                          const_cast<TemplatableValue<std::string> &>(record.value).value().c_str()); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -29,9 +29,11 @@ void MDNSComponent::setup() { | ||||
|     while (*service_type == '_') { | ||||
|       service_type++; | ||||
|     } | ||||
|     MDNS.addService(service_type, proto, service.port); | ||||
|     uint16_t port = const_cast<TemplatableValue<uint16_t> &>(service.port).value(); | ||||
|     MDNS.addService(service_type, proto, port); | ||||
|     for (const auto &record : service.txt_records) { | ||||
|       MDNS.addServiceTxt(service_type, proto, record.key.c_str(), record.value.c_str()); | ||||
|       MDNS.addServiceTxt(service_type, proto, record.key.c_str(), | ||||
|                          const_cast<TemplatableValue<std::string> &>(record.value).value().c_str()); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <vector> | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/defines.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/preferences.h" | ||||
| #include <utility> | ||||
| #include <vector> | ||||
|  | ||||
| namespace esphome { | ||||
|  | ||||
| @@ -27,7 +28,7 @@ template<typename T, typename... X> class TemplatableValue { | ||||
|   TemplatableValue() : type_(NONE) {} | ||||
|  | ||||
|   template<typename F, enable_if_t<!is_invocable<F, X...>::value, int> = 0> | ||||
|   TemplatableValue(F value) : type_(VALUE), value_(value) {} | ||||
|   TemplatableValue(F value) : type_(VALUE), value_(std::move(value)) {} | ||||
|  | ||||
|   template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0> | ||||
|   TemplatableValue(F f) : type_(LAMBDA), f_(f) {} | ||||
|   | ||||
| @@ -4,3 +4,10 @@ wifi: | ||||
|  | ||||
| mdns: | ||||
|   disabled: false | ||||
|   services: | ||||
|     - service: _test_service | ||||
|       protocol: _tcp | ||||
|       port: 8888 | ||||
|       txt: | ||||
|         static_string: Anything | ||||
|         templated_string: !lambda return "Something else"; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user