main.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "SensorMesh.h"
  2. #ifdef DISPLAY_CLASS
  3. #include "UITask.h"
  4. static UITask ui_task(display);
  5. #endif
  6. class MyMesh : public SensorMesh {
  7. public:
  8. MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables)
  9. : SensorMesh(board, radio, ms, rng, rtc, tables),
  10. battery_data(12*24, 5*60) // 24 hours worth of battery data, every 5 minutes
  11. {
  12. }
  13. protected:
  14. /* ========================== custom logic here ========================== */
  15. Trigger low_batt, critical_batt;
  16. TimeSeriesData battery_data;
  17. void onSensorDataRead() override {
  18. float batt_voltage = getVoltage(TELEM_CHANNEL_SELF);
  19. battery_data.recordData(getRTCClock(), batt_voltage); // record battery
  20. alertIf(batt_voltage < 3.4f, critical_batt, HIGH_PRI_ALERT, "Battery is critical!");
  21. alertIf(batt_voltage < 3.6f, low_batt, LOW_PRI_ALERT, "Battery is low");
  22. }
  23. int querySeriesData(uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg dest[], int max_num) override {
  24. battery_data.calcMinMaxAvg(getRTCClock(), start_secs_ago, end_secs_ago, &dest[0], TELEM_CHANNEL_SELF, LPP_VOLTAGE);
  25. return 1;
  26. }
  27. /* ======================================================================= */
  28. };
  29. StdRNG fast_rng;
  30. SimpleMeshTables tables;
  31. MyMesh the_mesh(board, radio_driver, *new ArduinoMillis(), fast_rng, rtc_clock, tables);
  32. void halt() {
  33. while (1) ;
  34. }
  35. static char command[120];
  36. void setup() {
  37. Serial.begin(115200);
  38. delay(1000);
  39. board.begin();
  40. #ifdef DISPLAY_CLASS
  41. if (display.begin()) {
  42. display.startFrame();
  43. display.print("Please wait...");
  44. display.endFrame();
  45. }
  46. #endif
  47. if (!radio_init()) { halt(); }
  48. fast_rng.begin(radio_get_rng_seed());
  49. FILESYSTEM* fs;
  50. #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
  51. InternalFS.begin();
  52. fs = &InternalFS;
  53. IdentityStore store(InternalFS, "");
  54. #elif defined(ESP32)
  55. SPIFFS.begin(true);
  56. fs = &SPIFFS;
  57. IdentityStore store(SPIFFS, "/identity");
  58. #elif defined(RP2040_PLATFORM)
  59. LittleFS.begin();
  60. fs = &LittleFS;
  61. IdentityStore store(LittleFS, "/identity");
  62. store.begin();
  63. #else
  64. #error "need to define filesystem"
  65. #endif
  66. if (!store.load("_main", the_mesh.self_id)) {
  67. MESH_DEBUG_PRINTLN("Generating new keypair");
  68. the_mesh.self_id = radio_new_identity(); // create new random identity
  69. int count = 0;
  70. while (count < 10 && (the_mesh.self_id.pub_key[0] == 0x00 || the_mesh.self_id.pub_key[0] == 0xFF)) { // reserved id hashes
  71. the_mesh.self_id = radio_new_identity(); count++;
  72. }
  73. store.save("_main", the_mesh.self_id);
  74. }
  75. Serial.print("Sensor ID: ");
  76. mesh::Utils::printHex(Serial, the_mesh.self_id.pub_key, PUB_KEY_SIZE); Serial.println();
  77. command[0] = 0;
  78. sensors.begin();
  79. the_mesh.begin(fs);
  80. #ifdef DISPLAY_CLASS
  81. ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
  82. #endif
  83. // send out initial Advertisement to the mesh
  84. the_mesh.sendSelfAdvertisement(16000);
  85. }
  86. void loop() {
  87. int len = strlen(command);
  88. while (Serial.available() && len < sizeof(command)-1) {
  89. char c = Serial.read();
  90. if (c != '\n') {
  91. command[len++] = c;
  92. command[len] = 0;
  93. }
  94. Serial.print(c);
  95. }
  96. if (len == sizeof(command)-1) { // command buffer full
  97. command[sizeof(command)-1] = '\r';
  98. }
  99. if (len > 0 && command[len - 1] == '\r') { // received complete line
  100. command[len - 1] = 0; // replace newline with C string null terminator
  101. char reply[160];
  102. the_mesh.handleCommand(0, command, reply); // NOTE: there is no sender_timestamp via serial!
  103. if (reply[0]) {
  104. Serial.print(" -> "); Serial.println(reply);
  105. }
  106. command[0] = 0; // reset command buffer
  107. }
  108. the_mesh.loop();
  109. sensors.loop();
  110. #ifdef DISPLAY_CLASS
  111. ui_task.loop();
  112. #endif
  113. }