Allow mdns services to be exposed by config (#4202)

This commit is contained in:
Joakim Plate 2023-02-02 05:18:58 +01:00 committed by GitHub
parent e3d9c44bdc
commit 0554b06b7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 1 deletions

View file

@ -1,4 +1,10 @@
from esphome.const import CONF_ID from esphome.const import (
CONF_ID,
CONF_PORT,
CONF_PROTOCOL,
CONF_SERVICES,
CONF_SERVICE,
)
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.core import CORE, coroutine_with_priority from esphome.core import CORE, coroutine_with_priority
@ -8,6 +14,8 @@ DEPENDENCIES = ["network"]
mdns_ns = cg.esphome_ns.namespace("mdns") mdns_ns = cg.esphome_ns.namespace("mdns")
MDNSComponent = mdns_ns.class_("MDNSComponent", cg.Component) MDNSComponent = mdns_ns.class_("MDNSComponent", cg.Component)
MDNSTXTRecord = mdns_ns.struct("MDNSTXTRecord")
MDNSService = mdns_ns.struct("MDNSService")
def _remove_id_if_disabled(value): def _remove_id_if_disabled(value):
@ -17,18 +25,50 @@ def _remove_id_if_disabled(value):
return value return value
CONF_TXT = "txt"
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},
}
)
CONF_DISABLED = "disabled" CONF_DISABLED = "disabled"
CONFIG_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All(
cv.Schema( cv.Schema(
{ {
cv.GenerateID(): cv.declare_id(MDNSComponent), cv.GenerateID(): cv.declare_id(MDNSComponent),
cv.Optional(CONF_DISABLED, default=False): cv.boolean, cv.Optional(CONF_DISABLED, default=False): cv.boolean,
cv.Optional(CONF_SERVICES, default=[]): cv.ensure_list(SERVICE_SCHEMA),
} }
), ),
_remove_id_if_disabled, _remove_id_if_disabled,
) )
def mdns_txt_record(key: str, value: str):
return cg.StructInitializer(
MDNSTXTRecord,
("key", key),
("value", value),
)
def mdns_service(
service: str, proto: str, port: int, txt_records: list[dict[str, str]]
):
return cg.StructInitializer(
MDNSService,
("service_type", service),
("proto", proto),
("port", port),
("txt_records", txt_records),
)
@coroutine_with_priority(55.0) @coroutine_with_priority(55.0)
async def to_code(config): async def to_code(config):
if CORE.using_arduino: if CORE.using_arduino:
@ -46,3 +86,15 @@ async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config) await cg.register_component(var, config)
for service in config[CONF_SERVICES]:
txt = [
mdns_txt_record(txt_key, txt_value)
for txt_key, txt_value in service[CONF_TXT].items()
]
exp = mdns_service(
service[CONF_SERVICE], service[CONF_PROTOCOL], service[CONF_PORT], txt
)
cg.add(var.add_extra_service(exp))

View file

@ -90,6 +90,8 @@ void MDNSComponent::compile_records_() {
} }
#endif #endif
this->services_.insert(this->services_.end(), this->services_extra_.begin(), this->services_extra_.end());
if (this->services_.empty()) { if (this->services_.empty()) {
// Publish "http" service if not using native API // Publish "http" service if not using native API
// This is just to have *some* mDNS service so that .local resolution works // This is just to have *some* mDNS service so that .local resolution works

View file

@ -33,7 +33,10 @@ class MDNSComponent : public Component {
#endif #endif
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
void add_extra_service(MDNSService service) { services_extra_.push_back(std::move(service)); }
protected: protected:
std::vector<MDNSService> services_extra_{};
std::vector<MDNSService> services_{}; std::vector<MDNSService> services_{};
std::string hostname_; std::string hostname_;
void compile_records_(); void compile_records_();