// SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2026 Pionix GmbH and Contributors to EVerest #include "charge_bridge/utilities/string.hpp" #include #include #include #include namespace charge_bridge { namespace { std::string to_string(discovery_device_type val) { switch (val) { case discovery_device_type::CB_EV: return "CB-CCS-EV-LU"; case discovery_device_type::CB_EVSE: return "CB-CCS-EVSE-LU"; default: return "INVALID"; } } bool is_cb_match(std::string const& board_type, discovery_device_type discriminator) { auto result = board_type == to_string(discriminator); return result; } } // namespace const std::string discovery::discovery_id = "_chargebridge._udp.local"; discovery::discovery(discovery_device_type type) : m_type(type) { using namespace std::chrono_literals; m_timer.set_timeout(1s); for (auto const& item : everest::lib::io::socket::get_all_interaces()) { add_client(item.name); } } discovery::discovery(discovery_device_type type, std::set const& interfaces, bool excluding) : m_type(type) { using namespace std::chrono_literals; m_timer.set_timeout(1s); for (auto const& item : everest::lib::io::socket::get_all_interaces()) { if (not interfaces.empty()) { if (interfaces.count(item.name) == 1 and excluding) { continue; } if (interfaces.count(item.name) == 0 and not excluding) { continue; } } std::cout << " using interface: " << item.name << std::endl; add_client(item.name); } } void discovery::add_client(std::string const& interface) { auto client = std::make_unique(interface); client->set_rx_handler([&](auto const& data, auto&) { auto discovery = everest::lib::io::mdns::parse_mdns_packet(data.buffer); if (discovery.has_value()) { if (m_registry.update(discovery.value())) { query_registry(); } } }); m_mdns.push_back(std::move(client)); } void discovery::query_registry() { auto obj = m_registry.get(); for (auto const& [key, value] : obj) { if (not utilities::string_ends_with(key, discovery_id)) { continue; } if (not value.txt.count("board_type") or not is_cb_match(value.txt.at("board_type"), m_type)) { continue; } if (not m_on_discover) { continue; } m_on_discover(value.ip); return; } } void discovery::set_discovery_callback(discovery_cb const& cb) { m_on_discover = cb; } bool discovery::register_events(everest::lib::io::event::fd_event_handler& handler) { auto result = true; for (auto& item : m_mdns) { if (item) { result = handler.register_event_handler(item.get()) && result; } } handler.register_event_handler(&m_timer, [&](auto) { for (auto& item : m_mdns) { item->get_raw_handler()->query(discovery_id); } }); return result; } bool discovery::unregister_events(everest::lib::io::event::fd_event_handler& handler) { auto result = true; for (auto& item : m_mdns) { if (item) { result = handler.unregister_event_handler(item.get()) && result; } } handler.unregister_event_handler(&m_timer); return result; } } // namespace charge_bridge