// NetworkInfo - a live dashboard of the Thread mesh, printed every 5 s.
//
// Shows the node's role and addresses, the partition it belongs to, and the
// neighbor table (who this node hears directly, with link quality).
//
// It also demonstrates the second API level of NiusThread: anything the
// friendly Thread.xxx() API doesn't cover is available through the official
// OpenThread C API - grab the instance with Thread.instance() and call any
// otXxx() function.

#include <NiusThread.h>

extern "C" {
#include <openthread/thread.h>   // official OpenThread API
#include <openthread/ip6.h>
}

static const uint8_t kNetworkKey[16] = {
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
    0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
};

void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 3000) {}

  Thread.begin();
  Thread.setNetwork("ArduinoNRF", 11, 0xBEEF, kNetworkKey);
  Thread.start();
  Serial.println("NetworkInfo: attaching...");
}

static void printDashboard() {
  otInstance *ot = Thread.instance();

  Serial.println("--------------------------------------------------");
  Serial.print("role: ");
  Serial.print(Thread.roleString());
  Serial.print("   rloc16: 0x");
  Serial.println(Thread.rloc16(), HEX);

  if (!Thread.isAttached()) {
    return;
  }

  // Partition + leader info (official OpenThread API).
  Serial.print("partition: 0x");
  Serial.println(otThreadGetPartitionId(ot), HEX);

  // Mesh-local EID: this node's stable IPv6 address inside the mesh.
  char addr[OT_IP6_ADDRESS_STRING_SIZE];
  otIp6AddressToString(otThreadGetMeshLocalEid(ot), addr, sizeof(addr));
  Serial.print("mesh-local address: ");
  Serial.println(addr);

  // Neighbor table: every node we hear directly.
  otNeighborInfoIterator it = OT_NEIGHBOR_INFO_ITERATOR_INIT;
  otNeighborInfo         nb;
  bool                   any = false;

  while (otThreadGetNextNeighborInfo(ot, &it, &nb) == OT_ERROR_NONE) {
    if (!any) {
      Serial.println("neighbors:");
      any = true;
    }
    Serial.print("  rloc16=0x");
    Serial.print(nb.mRloc16, HEX);
    Serial.print(nb.mIsChild ? "  child " : "  router");
    Serial.print("  rssi=");
    Serial.print(nb.mLastRssi);
    Serial.println(" dBm");
  }
  if (!any) {
    Serial.println("neighbors: none (single-node network)");
  }
}

void loop() {
  static uint32_t lastPrint = 0;

  Thread.process();

  if (millis() - lastPrint >= 5000) {
    lastPrint = millis();
    printDashboard();
  }
}
