main.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <Arduino.h> // needed for PlatformIO
  2. #include <Mesh.h>
  3. #include "MyMesh.h"
  4. #ifdef DISPLAY_CLASS
  5. #include "UITask.h"
  6. static UITask ui_task(display);
  7. #endif
  8. StdRNG fast_rng;
  9. SimpleMeshTables tables;
  10. MyMesh the_mesh(board, radio_driver, *new ArduinoMillis(), fast_rng, rtc_clock, tables);
  11. void halt() {
  12. while (1) ;
  13. }
  14. static char command[160];
  15. // For power saving
  16. unsigned long lastActive = 0; // mark last active time
  17. unsigned long nextSleepinSecs = 120; // next sleep in seconds. The first sleep (if enabled) is after 2 minutes from boot
  18. void setup() {
  19. Serial.begin(115200);
  20. delay(1000);
  21. board.begin();
  22. // For power saving
  23. lastActive = millis(); // mark last active time since boot
  24. #ifdef DISPLAY_CLASS
  25. if (display.begin()) {
  26. display.startFrame();
  27. display.setCursor(0, 0);
  28. display.print("Please wait...");
  29. display.endFrame();
  30. }
  31. #endif
  32. if (!radio_init()) {
  33. halt();
  34. }
  35. fast_rng.begin(radio_get_rng_seed());
  36. FILESYSTEM* fs;
  37. #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
  38. InternalFS.begin();
  39. fs = &InternalFS;
  40. IdentityStore store(InternalFS, "");
  41. #elif defined(ESP32)
  42. SPIFFS.begin(true);
  43. fs = &SPIFFS;
  44. IdentityStore store(SPIFFS, "/identity");
  45. #elif defined(RP2040_PLATFORM)
  46. LittleFS.begin();
  47. fs = &LittleFS;
  48. IdentityStore store(LittleFS, "/identity");
  49. store.begin();
  50. #else
  51. #error "need to define filesystem"
  52. #endif
  53. if (!store.load("_main", the_mesh.self_id)) {
  54. MESH_DEBUG_PRINTLN("Generating new keypair");
  55. the_mesh.self_id = radio_new_identity(); // create new random identity
  56. int count = 0;
  57. while (count < 10 && (the_mesh.self_id.pub_key[0] == 0x00 || the_mesh.self_id.pub_key[0] == 0xFF)) { // reserved id hashes
  58. the_mesh.self_id = radio_new_identity(); count++;
  59. }
  60. store.save("_main", the_mesh.self_id);
  61. }
  62. Serial.print("Repeater ID: ");
  63. mesh::Utils::printHex(Serial, the_mesh.self_id.pub_key, PUB_KEY_SIZE); Serial.println();
  64. command[0] = 0;
  65. sensors.begin();
  66. the_mesh.begin(fs);
  67. #ifdef DISPLAY_CLASS
  68. ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
  69. #endif
  70. // send out initial Advertisement to the mesh
  71. the_mesh.sendSelfAdvertisement(16000);
  72. }
  73. void loop() {
  74. int len = strlen(command);
  75. while (Serial.available() && len < sizeof(command)-1) {
  76. char c = Serial.read();
  77. if (c != '\n') {
  78. command[len++] = c;
  79. command[len] = 0;
  80. Serial.print(c);
  81. }
  82. if (c == '\r') break;
  83. }
  84. if (len == sizeof(command)-1) { // command buffer full
  85. command[sizeof(command)-1] = '\r';
  86. }
  87. if (len > 0 && command[len - 1] == '\r') { // received complete line
  88. Serial.print('\n');
  89. command[len - 1] = 0; // replace newline with C string null terminator
  90. char reply[160];
  91. the_mesh.handleCommand(0, command, reply); // NOTE: there is no sender_timestamp via serial!
  92. if (reply[0]) {
  93. Serial.print(" -> "); Serial.println(reply);
  94. }
  95. command[0] = 0; // reset command buffer
  96. }
  97. the_mesh.loop();
  98. sensors.loop();
  99. #ifdef DISPLAY_CLASS
  100. ui_task.loop();
  101. #endif
  102. rtc_clock.tick();
  103. if (the_mesh.getNodePrefs()->powersaving_enabled && // To check if power saving is enabled
  104. the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep
  105. if (!the_mesh.hasPendingWork()) { // No pending work. Safe to sleep
  106. board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet
  107. lastActive = millis();
  108. nextSleepinSecs = 5; // Default: To work for 5s and sleep again
  109. } else {
  110. nextSleepinSecs += 5; // When there is pending work, to work another 5s
  111. }
  112. }
  113. }