Jelajahi Sumber

Add statistics commands and response handling in MyMesh

- Introduced new commands for retrieving statistics: CMD_GET_STATS_CORE, CMD_GET_STATS_RADIO, and CMD_GET_STATS_PACKETS.
- Implemented corresponding response handling methods to format and send statistics data.
- Updated MyMesh constructor to initialize new member variables for managing statistics.
- Included StatsFormatHelper for formatting statistics replies.
agessaman 9 bulan lalu
induk
melakukan
df4dab8509
2 mengubah file dengan 69 tambahan dan 1 penghapusan
  1. 61 1
      examples/companion_radio/MyMesh.cpp
  2. 8 0
      examples/companion_radio/MyMesh.h

+ 61 - 1
examples/companion_radio/MyMesh.cpp

@@ -52,6 +52,9 @@
 #define CMD_SEND_PATH_DISCOVERY_REQ   52
 #define CMD_SET_FLOOD_SCOPE           54   // v8+
 #define CMD_SEND_CONTROL_DATA         55   // v8+
+#define CMD_GET_STATS_CORE            56
+#define CMD_GET_STATS_RADIO           57
+#define CMD_GET_STATS_PACKETS         58
 
 #define RESP_CODE_OK                  0
 #define RESP_CODE_ERR                 1
@@ -77,6 +80,9 @@
 #define RESP_CODE_CUSTOM_VARS         21
 #define RESP_CODE_ADVERT_PATH         22
 #define RESP_CODE_TUNING_PARAMS       23
+#define RESP_CODE_STATS_CORE          24
+#define RESP_CODE_STATS_RADIO         25
+#define RESP_CODE_STATS_PACKETS       26
 
 #define SEND_TIMEOUT_BASE_MILLIS        500
 #define FLOOD_SEND_TIMEOUT_FACTOR       16.0f
@@ -704,7 +710,7 @@ uint32_t MyMesh::calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t
 void MyMesh::onSendTimeout() {}
 
 MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store, AbstractUITask* ui)
-    : BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables),
+    : BaseChatMesh(radio, *(_ms_clock = new ArduinoMillis()), rng, rtc, *(_pkt_mgr = new StaticPoolPacketManager(16)), tables),
       _serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store), _ui(ui) {
   _iter_started = false;
   _cli_rescue = false;
@@ -1529,6 +1535,45 @@ void MyMesh::handleCmdFrame(size_t len) {
     } else {
       writeErrFrame(ERR_CODE_NOT_FOUND);
     }
+  } else if (cmd_frame[0] == CMD_GET_STATS_CORE) {
+    char json_reply[160];
+    formatStatsReply(json_reply);
+    int i = 0;
+    out_frame[i++] = RESP_CODE_STATS_CORE;
+    int json_len = strlen(json_reply);
+    if (i + json_len <= MAX_FRAME_SIZE) {
+      memcpy(&out_frame[i], json_reply, json_len);
+      i += json_len;
+      _serial->writeFrame(out_frame, i);
+    } else {
+      writeErrFrame(ERR_CODE_TABLE_FULL);
+    }
+  } else if (cmd_frame[0] == CMD_GET_STATS_RADIO) {
+    char json_reply[160];
+    formatRadioStatsReply(json_reply);
+    int i = 0;
+    out_frame[i++] = RESP_CODE_STATS_RADIO;
+    int json_len = strlen(json_reply);
+    if (i + json_len <= MAX_FRAME_SIZE) {
+      memcpy(&out_frame[i], json_reply, json_len);
+      i += json_len;
+      _serial->writeFrame(out_frame, i);
+    } else {
+      writeErrFrame(ERR_CODE_TABLE_FULL);
+    }
+  } else if (cmd_frame[0] == CMD_GET_STATS_PACKETS) {
+    char json_reply[160];
+    formatPacketStatsReply(json_reply);
+    int i = 0;
+    out_frame[i++] = RESP_CODE_STATS_PACKETS;
+    int json_len = strlen(json_reply);
+    if (i + json_len <= MAX_FRAME_SIZE) {
+      memcpy(&out_frame[i], json_reply, json_len);
+      i += json_len;
+      _serial->writeFrame(out_frame, i);
+    } else {
+      writeErrFrame(ERR_CODE_TABLE_FULL);
+    }
   } else if (cmd_frame[0] == CMD_FACTORY_RESET && memcmp(&cmd_frame[1], "reset", 5) == 0) {
     bool success = _store->formatFileSystem();
     if (success) {
@@ -1565,6 +1610,21 @@ void MyMesh::enterCLIRescue() {
   Serial.println("========= CLI Rescue =========");
 }
 
+void MyMesh::formatStatsReply(char *reply) {
+  // Use StatsFormatHelper
+  // Note: err_flags is private in Dispatcher, so we use 0
+  StatsFormatHelper::formatCoreStats(reply, board, *_ms_clock, 0, _pkt_mgr);
+}
+
+void MyMesh::formatRadioStatsReply(char *reply) {
+  StatsFormatHelper::formatRadioStats(reply, _radio, radio_driver, getTotalAirTime(), getReceiveAirTime());
+}
+
+void MyMesh::formatPacketStatsReply(char *reply) {
+  StatsFormatHelper::formatPacketStats(reply, radio_driver, getNumSentFlood(), getNumSentDirect(), 
+                                       getNumRecvFlood(), getNumRecvDirect());
+}
+
 void MyMesh::checkCLIRescueCmd() {
   int len = strlen(cli_command);
   while (Serial.available() && len < sizeof(cli_command)-1) {

+ 8 - 0
examples/companion_radio/MyMesh.h

@@ -69,6 +69,7 @@
 
 #include <helpers/BaseChatMesh.h>
 #include <helpers/TransportKeyStore.h>
+#include <helpers/StatsFormatHelper.h>
 
 /* -------------------------------------------------------------------------------------- */
 
@@ -170,6 +171,11 @@ private:
   void checkCLIRescueCmd();
   void checkSerialInterface();
 
+  // Stats methods
+  void formatStatsReply(char *reply);
+  void formatRadioStatsReply(char *reply);
+  void formatPacketStatsReply(char *reply);
+
   // helpers, short-cuts
   void savePrefs() { _store->savePrefs(_prefs, sensors.node_lat, sensors.node_lon); }
   void saveChannels() { _store->saveChannels(this); }
@@ -178,6 +184,8 @@ private:
 private:
   DataStore* _store;
   NodePrefs _prefs;
+  mesh::PacketManager* _pkt_mgr;  // stored for stats access
+  mesh::MillisecondClock* _ms_clock;  // stored for stats access
   uint32_t pending_login;
   uint32_t pending_status;
   uint32_t pending_telemetry, pending_discovery;   // pending _TELEMETRY_REQ