Merge branch 'master' into release/v3.3.x
This commit is contained in:
commit
5ccd9523d6
5 changed files with 566 additions and 26 deletions
|
|
@ -3,6 +3,9 @@
|
|||
OpenThread threadLeaderNode;
|
||||
DataSet dataset;
|
||||
|
||||
// Track last known device role for state change detection
|
||||
ot_device_role_t lastKnownRole = OT_ROLE_DISABLED;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
|
|
@ -27,8 +30,84 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
// Print network information every 5 seconds
|
||||
Serial.println("==============================================");
|
||||
threadLeaderNode.otPrintNetworkInformation(Serial);
|
||||
// Get current device role
|
||||
ot_device_role_t currentRole = threadLeaderNode.otGetDeviceRole();
|
||||
|
||||
// Only print network information when not detached
|
||||
if (currentRole != OT_ROLE_DETACHED && currentRole != OT_ROLE_DISABLED) {
|
||||
Serial.println("==============================================");
|
||||
Serial.println("OpenThread Network Information:");
|
||||
|
||||
// Basic network information
|
||||
Serial.printf("Role: %s\r\n", threadLeaderNode.otGetStringDeviceRole());
|
||||
Serial.printf("RLOC16: 0x%04x\r\n", threadLeaderNode.getRloc16());
|
||||
Serial.printf("Network Name: %s\r\n", threadLeaderNode.getNetworkName().c_str());
|
||||
Serial.printf("Channel: %d\r\n", threadLeaderNode.getChannel());
|
||||
Serial.printf("PAN ID: 0x%04x\r\n", threadLeaderNode.getPanId());
|
||||
|
||||
// Extended PAN ID
|
||||
const uint8_t *extPanId = threadLeaderNode.getExtendedPanId();
|
||||
if (extPanId) {
|
||||
Serial.print("Extended PAN ID: ");
|
||||
for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++) {
|
||||
Serial.printf("%02x", extPanId[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Network Key
|
||||
const uint8_t *networkKey = threadLeaderNode.getNetworkKey();
|
||||
if (networkKey) {
|
||||
Serial.print("Network Key: ");
|
||||
for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++) {
|
||||
Serial.printf("%02x", networkKey[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Mesh Local EID
|
||||
IPAddress meshLocalEid = threadLeaderNode.getMeshLocalEid();
|
||||
Serial.printf("Mesh Local EID: %s\r\n", meshLocalEid.toString().c_str());
|
||||
|
||||
// Leader RLOC
|
||||
IPAddress leaderRloc = threadLeaderNode.getLeaderRloc();
|
||||
Serial.printf("Leader RLOC: %s\r\n", leaderRloc.toString().c_str());
|
||||
|
||||
// Node RLOC
|
||||
IPAddress nodeRloc = threadLeaderNode.getRloc();
|
||||
Serial.printf("Node RLOC: %s\r\n", nodeRloc.toString().c_str());
|
||||
|
||||
// Demonstrate address listing with two different methods:
|
||||
// Method 1: Unicast addresses using counting API (individual access)
|
||||
Serial.println("\r\n--- Unicast Addresses (Using Count + Index API) ---");
|
||||
size_t unicastCount = threadLeaderNode.getUnicastAddressCount();
|
||||
for (size_t i = 0; i < unicastCount; i++) {
|
||||
IPAddress addr = threadLeaderNode.getUnicastAddress(i);
|
||||
Serial.printf(" [%zu]: %s\r\n", i, addr.toString().c_str());
|
||||
}
|
||||
|
||||
// Method 2: Multicast addresses using std::vector (bulk access)
|
||||
Serial.println("\r\n--- Multicast Addresses (Using std::vector API) ---");
|
||||
std::vector<IPAddress> allMulticast = threadLeaderNode.getAllMulticastAddresses();
|
||||
for (size_t i = 0; i < allMulticast.size(); i++) {
|
||||
Serial.printf(" [%zu]: %s\r\n", i, allMulticast[i].toString().c_str());
|
||||
}
|
||||
|
||||
// Check for role change and clear cache if needed (only when active)
|
||||
if (currentRole != lastKnownRole) {
|
||||
Serial.printf(
|
||||
"Role changed from %s to %s - clearing address cache\r\n", (lastKnownRole < 5) ? otRoleString[lastKnownRole] : "Unknown",
|
||||
threadLeaderNode.otGetStringDeviceRole()
|
||||
);
|
||||
threadLeaderNode.clearAllAddressCache();
|
||||
lastKnownRole = currentRole;
|
||||
}
|
||||
} else {
|
||||
Serial.printf("Thread Node Status: %s - Waiting for thread network start...\r\n", threadLeaderNode.otGetStringDeviceRole());
|
||||
|
||||
// Update role tracking even when detached/disabled, but don't clear cache
|
||||
lastKnownRole = currentRole;
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,63 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
// Print network information every 5 seconds
|
||||
Serial.println("==============================================");
|
||||
threadChildNode.otPrintNetworkInformation(Serial);
|
||||
// Get current device role
|
||||
ot_device_role_t currentRole = threadChildNode.otGetDeviceRole();
|
||||
|
||||
// Only print detailed network information when node is active
|
||||
if (currentRole != OT_ROLE_DETACHED && currentRole != OT_ROLE_DISABLED) {
|
||||
Serial.println("==============================================");
|
||||
Serial.println("OpenThread Network Information (Active Dataset):");
|
||||
|
||||
// Get and display the current active dataset
|
||||
const DataSet &activeDataset = threadChildNode.getCurrentDataSet();
|
||||
|
||||
Serial.printf("Role: %s\r\n", threadChildNode.otGetStringDeviceRole());
|
||||
Serial.printf("RLOC16: 0x%04x\r\n", threadChildNode.getRloc16());
|
||||
|
||||
// Dataset information
|
||||
Serial.printf("Network Name: %s\r\n", activeDataset.getNetworkName());
|
||||
Serial.printf("Channel: %d\r\n", activeDataset.getChannel());
|
||||
Serial.printf("PAN ID: 0x%04x\r\n", activeDataset.getPanId());
|
||||
|
||||
// Extended PAN ID from dataset
|
||||
const uint8_t *extPanId = activeDataset.getExtendedPanId();
|
||||
if (extPanId) {
|
||||
Serial.print("Extended PAN ID: ");
|
||||
for (int i = 0; i < OT_EXT_PAN_ID_SIZE; i++) {
|
||||
Serial.printf("%02x", extPanId[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Network Key from dataset
|
||||
const uint8_t *networkKey = activeDataset.getNetworkKey();
|
||||
if (networkKey) {
|
||||
Serial.print("Network Key: ");
|
||||
for (int i = 0; i < OT_NETWORK_KEY_SIZE; i++) {
|
||||
Serial.printf("%02x", networkKey[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Additional runtime information
|
||||
IPAddress meshLocalEid = threadChildNode.getMeshLocalEid();
|
||||
Serial.printf("Mesh Local EID: %s\r\n", meshLocalEid.toString().c_str());
|
||||
|
||||
IPAddress nodeRloc = threadChildNode.getRloc();
|
||||
Serial.printf("Node RLOC: %s\r\n", nodeRloc.toString().c_str());
|
||||
|
||||
IPAddress leaderRloc = threadChildNode.getLeaderRloc();
|
||||
Serial.printf("Leader RLOC: %s\r\n", leaderRloc.toString().c_str());
|
||||
|
||||
Serial.println();
|
||||
|
||||
} else {
|
||||
Serial.println("==============================================");
|
||||
Serial.printf("Thread Node Status: %s - Waiting for thread network start...\r\n", threadChildNode.otGetStringDeviceRole());
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ OpenThread KEYWORD1
|
|||
DataSet KEYWORD1
|
||||
ot_cmd_return_t KEYWORD1
|
||||
ot_device_role_t KEYWORD1
|
||||
OnReceiveCb_t KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
|
|
@ -59,6 +60,23 @@ stop KEYWORD2
|
|||
networkInterfaceUp KEYWORD2
|
||||
networkInterfaceDown KEYWORD2
|
||||
commitDataSet KEYWORD2
|
||||
getInstance KEYWORD2
|
||||
getCurrentDataSet KEYWORD2
|
||||
getMeshLocalPrefix KEYWORD2
|
||||
getMeshLocalEid KEYWORD2
|
||||
getLeaderRloc KEYWORD2
|
||||
getRloc KEYWORD2
|
||||
getRloc16 KEYWORD2
|
||||
getUnicastAddressCount KEYWORD2
|
||||
getUnicastAddress KEYWORD2
|
||||
getAllUnicastAddresses KEYWORD2
|
||||
getMulticastAddressCount KEYWORD2
|
||||
getMulticastAddress KEYWORD2
|
||||
getAllMulticastAddresses KEYWORD2
|
||||
clearUnicastAddressCache KEYWORD2
|
||||
clearMulticastAddressCache KEYWORD2
|
||||
clearAllAddressCache KEYWORD2
|
||||
end KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#if SOC_IEEE802154_SUPPORTED
|
||||
#if CONFIG_OPENTHREAD_ENABLED
|
||||
|
||||
#include "IPAddress.h"
|
||||
#include <vector>
|
||||
#include "esp_err.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
|
|
@ -132,16 +134,29 @@ const otOperationalDataset &DataSet::getDataset() const {
|
|||
}
|
||||
|
||||
void DataSet::setNetworkName(const char *name) {
|
||||
strncpy(mDataset.mNetworkName.m8, name, sizeof(mDataset.mNetworkName.m8));
|
||||
if (!name) {
|
||||
log_w("Network name is null");
|
||||
return;
|
||||
}
|
||||
// char m8[OT_NETWORK_KEY_SIZE + 1] bytes space by definition
|
||||
strncpy(mDataset.mNetworkName.m8, name, OT_NETWORK_KEY_SIZE);
|
||||
mDataset.mComponents.mIsNetworkNamePresent = true;
|
||||
}
|
||||
|
||||
void DataSet::setExtendedPanId(const uint8_t *extPanId) {
|
||||
if (!extPanId) {
|
||||
log_w("Extended PAN ID is null");
|
||||
return;
|
||||
}
|
||||
memcpy(mDataset.mExtendedPanId.m8, extPanId, OT_EXT_PAN_ID_SIZE);
|
||||
mDataset.mComponents.mIsExtendedPanIdPresent = true;
|
||||
}
|
||||
|
||||
void DataSet::setNetworkKey(const uint8_t *key) {
|
||||
if (!key) {
|
||||
log_w("Network key is null");
|
||||
return;
|
||||
}
|
||||
memcpy(mDataset.mNetworkKey.m8, key, OT_NETWORK_KEY_SIZE);
|
||||
mDataset.mComponents.mIsNetworkKeyPresent = true;
|
||||
}
|
||||
|
|
@ -181,10 +196,18 @@ void DataSet::apply(otInstance *instance) {
|
|||
}
|
||||
|
||||
// OpenThread Implementation
|
||||
bool OpenThread::otStarted = false;
|
||||
bool OpenThread::otStarted;
|
||||
otInstance *OpenThread::mInstance;
|
||||
DataSet OpenThread::mCurrentDataset;
|
||||
otNetworkKey OpenThread::mNetworkKey;
|
||||
|
||||
otInstance *OpenThread::mInstance = nullptr;
|
||||
OpenThread::OpenThread() {}
|
||||
OpenThread::OpenThread() {
|
||||
// static initialization (node data and stack starting information)
|
||||
otStarted = false;
|
||||
mCurrentDataset.clear(); // Initialize the current dataset
|
||||
memset(&mNetworkKey, 0, sizeof(mNetworkKey)); // Initialize the network key
|
||||
mInstance = nullptr;
|
||||
}
|
||||
|
||||
OpenThread::~OpenThread() {
|
||||
end();
|
||||
|
|
@ -214,13 +237,7 @@ void OpenThread::begin(bool OThreadAutoStart) {
|
|||
return;
|
||||
}
|
||||
log_d("OpenThread task created successfully");
|
||||
// get the OpenThread instance that will be used for all operations
|
||||
mInstance = esp_openthread_get_instance();
|
||||
if (!mInstance) {
|
||||
log_e("Error: Failed to initialize OpenThread instance");
|
||||
end();
|
||||
return;
|
||||
}
|
||||
|
||||
// starts Thread with default dataset from NVS or from IDF default settings
|
||||
if (OThreadAutoStart) {
|
||||
otOperationalDatasetTlvs dataset;
|
||||
|
|
@ -238,23 +255,46 @@ void OpenThread::begin(bool OThreadAutoStart) {
|
|||
log_i("AUTO start OpenThread done");
|
||||
}
|
||||
}
|
||||
|
||||
// get the OpenThread instance that will be used for all operations
|
||||
mInstance = esp_openthread_get_instance();
|
||||
if (!mInstance) {
|
||||
log_e("Error: Failed to initialize OpenThread instance");
|
||||
end();
|
||||
return;
|
||||
}
|
||||
|
||||
otStarted = true;
|
||||
}
|
||||
|
||||
void OpenThread::end() {
|
||||
if (!otStarted) {
|
||||
log_w("OpenThread already stopped");
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_ot_task != NULL) {
|
||||
vTaskDelete(s_ot_task);
|
||||
s_ot_task = NULL;
|
||||
// Clean up
|
||||
esp_openthread_deinit();
|
||||
esp_openthread_netif_glue_deinit();
|
||||
#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM
|
||||
ot_lwip_netif = NULL;
|
||||
#endif
|
||||
esp_netif_destroy(openthread_netif);
|
||||
esp_vfs_eventfd_unregister();
|
||||
}
|
||||
|
||||
// Clean up in reverse order of initialization
|
||||
if (openthread_netif != NULL) {
|
||||
esp_netif_destroy(openthread_netif);
|
||||
openthread_netif = NULL;
|
||||
}
|
||||
|
||||
esp_openthread_netif_glue_deinit();
|
||||
esp_openthread_deinit();
|
||||
esp_vfs_eventfd_unregister();
|
||||
|
||||
#if CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM
|
||||
ot_lwip_netif = NULL;
|
||||
#endif
|
||||
|
||||
mInstance = nullptr;
|
||||
otStarted = false;
|
||||
log_d("OpenThread ended successfully");
|
||||
}
|
||||
|
||||
void OpenThread::start() {
|
||||
|
|
@ -262,6 +302,7 @@ void OpenThread::start() {
|
|||
log_w("Error: OpenThread instance not initialized");
|
||||
return;
|
||||
}
|
||||
clearAllAddressCache(); // Clear cache when starting network
|
||||
otThreadSetEnabled(mInstance, true);
|
||||
log_d("Thread network started");
|
||||
}
|
||||
|
|
@ -271,6 +312,7 @@ void OpenThread::stop() {
|
|||
log_w("Error: OpenThread instance not initialized");
|
||||
return;
|
||||
}
|
||||
clearAllAddressCache(); // Clear cache when stopping network
|
||||
otThreadSetEnabled(mInstance, false);
|
||||
log_d("Thread network stopped");
|
||||
}
|
||||
|
|
@ -285,6 +327,7 @@ void OpenThread::networkInterfaceUp() {
|
|||
if (error != OT_ERROR_NONE) {
|
||||
log_e("Error: Failed to enable Thread interface (error code: %d)\n", error);
|
||||
}
|
||||
clearAllAddressCache(); // Clear cache when interface comes up
|
||||
log_d("OpenThread Network Interface is up");
|
||||
}
|
||||
|
||||
|
|
@ -312,6 +355,7 @@ void OpenThread::commitDataSet(const DataSet &dataset) {
|
|||
log_e("Error: Failed to commit dataset (error code: %d)\n", error);
|
||||
return;
|
||||
}
|
||||
clearAllAddressCache(); // Clear cache when dataset changes
|
||||
log_d("Dataset committed successfully");
|
||||
}
|
||||
|
||||
|
|
@ -360,6 +404,289 @@ void OpenThread::otPrintNetworkInformation(Stream &output) {
|
|||
output.println();
|
||||
}
|
||||
|
||||
// Get the Node Network Name
|
||||
String OpenThread::getNetworkName() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return String(); // Return empty String, not nullptr
|
||||
}
|
||||
const char *networkName = otThreadGetNetworkName(mInstance);
|
||||
return networkName ? String(networkName) : String();
|
||||
}
|
||||
|
||||
// Get the Node Extended PAN ID
|
||||
const uint8_t *OpenThread::getExtendedPanId() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return nullptr;
|
||||
}
|
||||
const otExtendedPanId *extPanId = otThreadGetExtendedPanId(mInstance);
|
||||
return extPanId ? extPanId->m8 : nullptr;
|
||||
}
|
||||
|
||||
// Get the Node Network Key
|
||||
const uint8_t *OpenThread::getNetworkKey() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return nullptr;
|
||||
}
|
||||
otThreadGetNetworkKey(mInstance, &mNetworkKey);
|
||||
return mNetworkKey.m8;
|
||||
}
|
||||
|
||||
// Get the Node Channel
|
||||
uint8_t OpenThread::getChannel() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return 0;
|
||||
}
|
||||
return otLinkGetChannel(mInstance);
|
||||
}
|
||||
|
||||
// Get the Node PAN ID
|
||||
uint16_t OpenThread::getPanId() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return 0;
|
||||
}
|
||||
return otLinkGetPanId(mInstance);
|
||||
}
|
||||
|
||||
// Get the OpenThread instance
|
||||
otInstance *OpenThread::getInstance() {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return nullptr;
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
// Get the current dataset
|
||||
const DataSet &OpenThread::getCurrentDataSet() const {
|
||||
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
mCurrentDataset.clear();
|
||||
return mCurrentDataset;
|
||||
}
|
||||
|
||||
otOperationalDataset dataset;
|
||||
otError error = otDatasetGetActive(mInstance, &dataset);
|
||||
|
||||
if (error == OT_ERROR_NONE) {
|
||||
mCurrentDataset.clear();
|
||||
|
||||
if (dataset.mComponents.mIsNetworkNamePresent) {
|
||||
mCurrentDataset.setNetworkName(dataset.mNetworkName.m8);
|
||||
}
|
||||
if (dataset.mComponents.mIsExtendedPanIdPresent) {
|
||||
mCurrentDataset.setExtendedPanId(dataset.mExtendedPanId.m8);
|
||||
}
|
||||
if (dataset.mComponents.mIsNetworkKeyPresent) {
|
||||
mCurrentDataset.setNetworkKey(dataset.mNetworkKey.m8);
|
||||
}
|
||||
if (dataset.mComponents.mIsChannelPresent) {
|
||||
mCurrentDataset.setChannel(dataset.mChannel);
|
||||
}
|
||||
if (dataset.mComponents.mIsPanIdPresent) {
|
||||
mCurrentDataset.setPanId(dataset.mPanId);
|
||||
}
|
||||
} else {
|
||||
log_w("Failed to get active dataset (error: %d)", error);
|
||||
mCurrentDataset.clear();
|
||||
}
|
||||
|
||||
return mCurrentDataset;
|
||||
}
|
||||
|
||||
// Get the Mesh Local Prefix
|
||||
const otMeshLocalPrefix *OpenThread::getMeshLocalPrefix() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return nullptr;
|
||||
}
|
||||
return otThreadGetMeshLocalPrefix(mInstance);
|
||||
}
|
||||
|
||||
// Get the Mesh-Local EID
|
||||
IPAddress OpenThread::getMeshLocalEid() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return IPAddress(IPv6); // Return empty IPv6 address
|
||||
}
|
||||
const otIp6Address *otAddr = otThreadGetMeshLocalEid(mInstance);
|
||||
if (!otAddr) {
|
||||
log_w("Failed to get Mesh Local EID");
|
||||
return IPAddress(IPv6);
|
||||
}
|
||||
return IPAddress(IPv6, otAddr->mFields.m8);
|
||||
}
|
||||
|
||||
// Get the Thread Leader RLOC
|
||||
IPAddress OpenThread::getLeaderRloc() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return IPAddress(IPv6); // Return empty IPv6 address
|
||||
}
|
||||
otIp6Address otAddr;
|
||||
otError error = otThreadGetLeaderRloc(mInstance, &otAddr);
|
||||
if (error != OT_ERROR_NONE) {
|
||||
log_w("Failed to get Leader RLOC");
|
||||
return IPAddress(IPv6);
|
||||
}
|
||||
return IPAddress(IPv6, otAddr.mFields.m8);
|
||||
}
|
||||
|
||||
// Get the Node RLOC
|
||||
IPAddress OpenThread::getRloc() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return IPAddress(IPv6); // Return empty IPv6 address
|
||||
}
|
||||
const otIp6Address *otAddr = otThreadGetRloc(mInstance);
|
||||
if (!otAddr) {
|
||||
log_w("Failed to get Node RLOC");
|
||||
return IPAddress(IPv6);
|
||||
}
|
||||
return IPAddress(IPv6, otAddr->mFields.m8);
|
||||
}
|
||||
|
||||
// Get the RLOC16 ID
|
||||
uint16_t OpenThread::getRloc16() const {
|
||||
if (!mInstance) {
|
||||
log_w("Error: OpenThread instance not initialized");
|
||||
return 0;
|
||||
}
|
||||
return otThreadGetRloc16(mInstance);
|
||||
}
|
||||
|
||||
// Populate unicast address cache from OpenThread
|
||||
void OpenThread::populateUnicastAddressCache() const {
|
||||
if (!mInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear existing cache
|
||||
mCachedUnicastAddresses.clear();
|
||||
|
||||
// Populate unicast addresses cache
|
||||
const otNetifAddress *addr = otIp6GetUnicastAddresses(mInstance);
|
||||
while (addr != nullptr) {
|
||||
mCachedUnicastAddresses.push_back(IPAddress(IPv6, addr->mAddress.mFields.m8));
|
||||
addr = addr->mNext;
|
||||
}
|
||||
|
||||
log_d("Populated unicast address cache with %zu addresses", mCachedUnicastAddresses.size());
|
||||
}
|
||||
|
||||
// Populate multicast address cache from OpenThread
|
||||
void OpenThread::populateMulticastAddressCache() const {
|
||||
if (!mInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear existing cache
|
||||
mCachedMulticastAddresses.clear();
|
||||
|
||||
// Populate multicast addresses cache
|
||||
const otNetifMulticastAddress *mAddr = otIp6GetMulticastAddresses(mInstance);
|
||||
while (mAddr != nullptr) {
|
||||
mCachedMulticastAddresses.push_back(IPAddress(IPv6, mAddr->mAddress.mFields.m8));
|
||||
mAddr = mAddr->mNext;
|
||||
}
|
||||
|
||||
log_d("Populated multicast address cache with %zu addresses", mCachedMulticastAddresses.size());
|
||||
}
|
||||
|
||||
// Clear unicast address cache
|
||||
void OpenThread::clearUnicastAddressCache() const {
|
||||
mCachedUnicastAddresses.clear();
|
||||
log_d("Cleared unicast address cache");
|
||||
}
|
||||
|
||||
// Clear multicast address cache
|
||||
void OpenThread::clearMulticastAddressCache() const {
|
||||
mCachedMulticastAddresses.clear();
|
||||
log_d("Cleared multicast address cache");
|
||||
}
|
||||
|
||||
// Clear all address caches
|
||||
void OpenThread::clearAllAddressCache() const {
|
||||
mCachedUnicastAddresses.clear();
|
||||
mCachedMulticastAddresses.clear();
|
||||
log_d("Cleared all address caches");
|
||||
}
|
||||
|
||||
// Get count of unicast addresses
|
||||
size_t OpenThread::getUnicastAddressCount() const {
|
||||
// Populate cache if empty
|
||||
if (mCachedUnicastAddresses.empty()) {
|
||||
populateUnicastAddressCache();
|
||||
}
|
||||
|
||||
return mCachedUnicastAddresses.size();
|
||||
}
|
||||
|
||||
// Get unicast address by index
|
||||
IPAddress OpenThread::getUnicastAddress(size_t index) const {
|
||||
// Populate cache if empty
|
||||
if (mCachedUnicastAddresses.empty()) {
|
||||
populateUnicastAddressCache();
|
||||
}
|
||||
|
||||
if (index >= mCachedUnicastAddresses.size()) {
|
||||
log_w("Unicast address index %zu out of range (max: %zu)", index, mCachedUnicastAddresses.size());
|
||||
return IPAddress(IPv6);
|
||||
}
|
||||
|
||||
return mCachedUnicastAddresses[index];
|
||||
}
|
||||
|
||||
// Get all unicast addresses
|
||||
std::vector<IPAddress> OpenThread::getAllUnicastAddresses() const {
|
||||
// Populate cache if empty
|
||||
if (mCachedUnicastAddresses.empty()) {
|
||||
populateUnicastAddressCache();
|
||||
}
|
||||
|
||||
return mCachedUnicastAddresses; // Return copy of cached vector
|
||||
}
|
||||
|
||||
// Get count of multicast addresses
|
||||
size_t OpenThread::getMulticastAddressCount() const {
|
||||
// Populate cache if empty
|
||||
if (mCachedMulticastAddresses.empty()) {
|
||||
populateMulticastAddressCache();
|
||||
}
|
||||
|
||||
return mCachedMulticastAddresses.size();
|
||||
}
|
||||
|
||||
// Get multicast address by index
|
||||
IPAddress OpenThread::getMulticastAddress(size_t index) const {
|
||||
// Populate cache if empty
|
||||
if (mCachedMulticastAddresses.empty()) {
|
||||
populateMulticastAddressCache();
|
||||
}
|
||||
|
||||
if (index >= mCachedMulticastAddresses.size()) {
|
||||
log_w("Multicast address index %zu out of range (max: %zu)", index, mCachedMulticastAddresses.size());
|
||||
return IPAddress(IPv6);
|
||||
}
|
||||
|
||||
return mCachedMulticastAddresses[index];
|
||||
}
|
||||
|
||||
// Get all multicast addresses
|
||||
std::vector<IPAddress> OpenThread::getAllMulticastAddresses() const {
|
||||
// Populate cache if empty
|
||||
if (mCachedMulticastAddresses.empty()) {
|
||||
populateMulticastAddressCache();
|
||||
}
|
||||
|
||||
return mCachedMulticastAddresses; // Return copy of cached vector
|
||||
}
|
||||
|
||||
OpenThread OThread;
|
||||
|
||||
#endif /* CONFIG_OPENTHREAD_ENABLED */
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include <openthread/dataset_ftd.h>
|
||||
#include <esp_openthread.h>
|
||||
#include <Arduino.h>
|
||||
#include "IPAddress.h"
|
||||
#include <vector>
|
||||
|
||||
typedef enum {
|
||||
OT_ROLE_DISABLED = 0, ///< The Thread stack is disabled.
|
||||
|
|
@ -96,9 +98,68 @@ public:
|
|||
// Set the dataset
|
||||
void commitDataSet(const DataSet &dataset);
|
||||
|
||||
// Get the Node Network Name
|
||||
String getNetworkName() const;
|
||||
|
||||
// Get the Node Extended PAN ID
|
||||
const uint8_t *getExtendedPanId() const;
|
||||
|
||||
// Get the Node Network Key
|
||||
const uint8_t *getNetworkKey() const;
|
||||
|
||||
// Get the Node Channel
|
||||
uint8_t getChannel() const;
|
||||
|
||||
// Get the Node PAN ID
|
||||
uint16_t getPanId() const;
|
||||
|
||||
// Get the OpenThread instance
|
||||
otInstance *getInstance();
|
||||
|
||||
// Get the current dataset
|
||||
const DataSet &getCurrentDataSet() const;
|
||||
|
||||
// Get the Mesh Local Prefix
|
||||
const otMeshLocalPrefix *getMeshLocalPrefix() const;
|
||||
|
||||
// Get the Mesh-Local EID
|
||||
IPAddress getMeshLocalEid() const;
|
||||
|
||||
// Get the Thread Leader RLOC
|
||||
IPAddress getLeaderRloc() const;
|
||||
|
||||
// Get the Node RLOC
|
||||
IPAddress getRloc() const;
|
||||
|
||||
// Get the RLOC16 ID
|
||||
uint16_t getRloc16() const;
|
||||
|
||||
// Address management with caching
|
||||
size_t getUnicastAddressCount() const;
|
||||
IPAddress getUnicastAddress(size_t index) const;
|
||||
std::vector<IPAddress> getAllUnicastAddresses() const;
|
||||
|
||||
size_t getMulticastAddressCount() const;
|
||||
IPAddress getMulticastAddress(size_t index) const;
|
||||
std::vector<IPAddress> getAllMulticastAddresses() const;
|
||||
|
||||
// Cache management
|
||||
void clearUnicastAddressCache() const;
|
||||
void clearMulticastAddressCache() const;
|
||||
void clearAllAddressCache() const;
|
||||
|
||||
private:
|
||||
static otInstance *mInstance;
|
||||
DataSet mCurrentDataSet;
|
||||
static DataSet mCurrentDataset; // Current dataset being used by the OpenThread instance.
|
||||
static otNetworkKey mNetworkKey; // Static storage to persist after function return
|
||||
|
||||
// Address caching for performance (user-controlled)
|
||||
mutable std::vector<IPAddress> mCachedUnicastAddresses;
|
||||
mutable std::vector<IPAddress> mCachedMulticastAddresses;
|
||||
|
||||
// Internal cache management
|
||||
void populateUnicastAddressCache() const;
|
||||
void populateMulticastAddressCache() const;
|
||||
};
|
||||
|
||||
extern OpenThread OThread;
|
||||
|
|
|
|||
Loading…
Reference in a new issue