Skip to content

Commit

Permalink
feat: Task implementation for espressif
Browse files Browse the repository at this point in the history
  • Loading branch information
feelfreelinux committed Jan 28, 2025
1 parent 4c3e56e commit 79cf88e
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 27 deletions.
2 changes: 2 additions & 0 deletions include/bell/mdns/Browser.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class Browser {

std::vector<net::IpAddress> addresses;

DiscoveredRecord() = default;

bool operator==(const DiscoveredRecord& other) const {
return name == other.name && regType == other.regType &&
domain == other.domain && interfaceIndex == other.interfaceIndex;
Expand Down
66 changes: 44 additions & 22 deletions main/platform/esp/MDNSBrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// Standar includes
#include <array>
#include <iostream>
#include <stdexcept>
#include <string>

Expand All @@ -18,14 +19,13 @@ using namespace bell;
class implMDNSBrowser : public mdns::Browser {
public:
implMDNSBrowser(std::string regType, std::string regDomain,
int interfaceIndex, DiscoveryEventCallback onEvent,
bool autoResolveService = true, bool resolveIpv6 = true)
DiscoveryEventCallback onEvent)
: regType(std::move(regType)),
regDomain(std::move(regDomain)),
onEvent(std::move(onEvent)) {
// Extract the protocol from the regType
serviceType = regType.substr(0, regType.find_first_of('.'));
proto = regType.substr(regType.find_first_of('.') + 1);
serviceType = this->regType.substr(0, this->regType.find_first_of('.'));
proto = this->regType.substr(this->regType.find_first_of('.') + 1);
}

// Delete copy constructor and copy assignment operator
Expand All @@ -35,8 +35,6 @@ class implMDNSBrowser : public mdns::Browser {
~implMDNSBrowser() override { stopDiscovery(); }

private:
const char* LOG_TAG = "EspressifMDNSBrowser";

std::string regType;
std::string regDomain;
std::string proto;
Expand All @@ -45,17 +43,18 @@ class implMDNSBrowser : public mdns::Browser {

const int maxResults = 32;

std::vector<DiscoveredRecord> discoveredRecords;
std::vector<DiscoveredRecord> cachedRecords;
std::vector<DiscoveredRecord> receivedRecords;

std::vector<DiscoveredRecord> parseResults(mdns_result_t* results) {
void parseResults(mdns_result_t* results) {
mdns_result_t* r = results;
mdns_ip_addr_t* a = nullptr;
std::vector<DiscoveredRecord> records;

while (r) {
DiscoveredRecord record;

record.interfaceIndex = r->esp_netif
// Assign netif index
record.interfaceIndex = esp_netif_get_netif_impl_index(r->esp_netif);

if (r->instance_name) {
record.name = r->instance_name;
Expand All @@ -68,16 +67,18 @@ class implMDNSBrowser : public mdns::Browser {
record.addressResolved = true;
}



a = r->addr;
while (a) {
if (a->addr.type == IPADDR_TYPE_V4) {
std::array<char, IP4ADDR_STRLEN_MAX> strCharData{};
esp_ip4addr_ntoa(&a->addr.u_addr.ip4, strCharData.data(),
IP4ADDR_STRLEN_MAX);
std::string ipStr(strCharData.data());
record.addresses.push_back(net::IpAddress::fromString(ipStr));
auto ip = net::IpAddress::fromString(ipStr);

if (ip.has_value()) {
record.addresses.push_back(ip.value());
}
} else if (a->addr.type == IPADDR_TYPE_V6) {
// TODO: Implement IPv6 support
// std::array<char, IP6ADDR_STRLEN_MAX> strCharData{};
Expand All @@ -98,11 +99,31 @@ class implMDNSBrowser : public mdns::Browser {
&r->txt[x].value[r->txt_value_len[x]])});
}

records.push_back(record);
// Notify of new services
if (std::find(cachedRecords.begin(), cachedRecords.end(), record) ==
cachedRecords.end()) {
onEvent(mdns::EventType::ServiceAdded, record);
if (record.serviceResolved) {
onEvent(mdns::EventType::ServiceResolved, record);
}
if (record.addressResolved) {
onEvent(mdns::EventType::AddressResolved, record);
}
}

receivedRecords.push_back(record);
r = r->next;
}

publishDiscovered();
// Notify of removed services
for (auto& cachedRecord : cachedRecords) {
if (std::find(receivedRecords.begin(), receivedRecords.end(),
cachedRecord) == receivedRecords.end()) {
onEvent(mdns::EventType::ServiceRemoved, cachedRecord);
}
}

cachedRecords.assign(receivedRecords.begin(), receivedRecords.end());
}

void processEvents(int timeoutMs) override {
Expand All @@ -111,11 +132,13 @@ class implMDNSBrowser : public mdns::Browser {
esp_err_t err = mdns_query_ptr(serviceType.c_str(), proto.c_str(),
timeoutMs, maxResults, &results);
if (err) {
BELL_LOG(
error, "MDNSBrowser",
"Failed to query mdns services. Service type: {}, proto: {}, err: {}",
serviceType, proto, static_cast<int>(err));
throw std::runtime_error("Could not query mdns services");
}

processResults(results);

mdns_query_results_free(results);
}

Expand All @@ -132,9 +155,8 @@ class implMDNSBrowser : public mdns::Browser {

std::unique_ptr<mdns::Browser> mdns::Browser::startDiscovery(
const std::string& regType, const std::string& regDomain,
int interfaceIndex, const DiscoveryEventCallback& onEvent,
bool autoResolveService, bool /*autoResolveAddresses*/, bool resolveIpv6) {
return std::make_unique<implMDNSBrowser>(regType, regDomain, interfaceIndex,
onEvent, autoResolveService,
resolveIpv6);
int /*interfaceIndex*/, const DiscoveryEventCallback& onEvent,
bool /*autoResolveService*/, bool /*autoResolveAddresses*/,
bool /*resolveIpv6*/) {
return std::make_unique<implMDNSBrowser>(regType, regDomain, onEvent);
}
86 changes: 81 additions & 5 deletions main/platform/esp/Task.cpp
Original file line number Diff line number Diff line change
@@ -1,36 +1,112 @@
#include "bell/utils/Task.h"

// Library includes
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/timers.h>
#include "sdkconfig.h"

// Bell includes
#include <bell/Logger.h>
#include <pthread.h>
#include <algorithm>

using namespace bell::utils;

class Task::Impl {
public:
Impl(const std::string& taskName, int stackSize, int espPriority,
Impl(std::string taskName, int stackSize, int espPriority,
TaskCore espTaskCore, bool espStackOnPsram)
: stackSize(stackSize),
espTaskCore(espTaskCore),
espStackOnPsram(espStackOnPsram),
espPriority(espPriority),
taskName(taskName) {}
taskName(std::move(taskName)) {

if (espStackOnPsram) {
xStack = static_cast<StackType_t*>(
heap_caps_malloc(stackSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));

xTaskBuffer = static_cast<StaticTask_t*>(heap_caps_malloc(
sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));
}
}
~Impl() {
if (xStack) {
heap_caps_free(xStack);

// Create a cleanup timer for PSRAM task TCB
auto* timerHandle =
xTimerCreate("TaskCleanupTimer", pdMS_TO_TICKS(5000), pdFALSE,
xTaskBuffer, [](TimerHandle_t timer) {
heap_caps_free(pvTimerGetTimerID(timer));
xTimerDelete(timer, portMAX_DELAY);
});
xTimerStart(timerHandle, portMAX_DELAY);
}
};

// Delete copy constructor and copy assignment operator
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;

bool startTask(Task* task) { return false; }
// Task entry point
void taskEntryPoint() {
if (taskPtr) {
taskPtr->runTask();
}
}

// Task entry point shim, used to call the mmber method
static void taskEntryPointShim(void* task) {
Task::Impl* taskPtr = static_cast<Task::Impl*>(task);
taskPtr->taskEntryPoint();
}

bool startTask(Task* task) {
taskPtr = task;
if (espStackOnPsram) {
// Create the task with previously allocated stack on PSRAM
xTaskHandle = xTaskCreateStaticPinnedToCore(
taskEntryPointShim, this->taskName.c_str(), this->stackSize, this,
this->espPriority + CONFIG_PTHREAD_TASK_PRIO_DEFAULT, xStack,
xTaskBuffer, getFreeRTOSTaskCore());
} else {
// Create the task with default stack allocation
if (xTaskCreatePinnedToCore(
taskEntryPointShim, this->taskName.c_str(), this->stackSize, this,
this->espPriority + CONFIG_PTHREAD_TASK_PRIO_DEFAULT,
&xTaskHandle, getFreeRTOSTaskCore()) != pdPASS) {
xTaskHandle = nullptr;
}
}

return xTaskHandle != nullptr;
}

private:
int stackSize = 0;
TaskCore espTaskCore;
bool espStackOnPsram = false;
int espPriority;
std::string taskName;

StaticTask_t* xTaskBuffer;
StackType_t* xStack;
TaskHandle_t xTaskHandle;
Task* taskPtr;

// Returns the FreeRTOS task core
BaseType_t getFreeRTOSTaskCore() {
switch (espTaskCore) {
case TaskCore::Core0:
return 0;
case TaskCore::Core1:
return 1;
case TaskCore::CoreAny:
return tskNO_AFFINITY;
}

return tskNO_AFFINITY;
}
};

// Task constructor and member methods
Expand Down

0 comments on commit 79cf88e

Please sign in to comment.