Browse Source

feat: add stats-extpower CLI command for INA3221 power monitoring

Add a serial-only `stats-extpower` command that returns per-channel
voltage and current readings from the INA3221 external power monitoring
board as JSON. Returns an error message if no supported hardware is
detected.

Changes:
- New stats-extpower CLI command in CommonCLI.cpp
- formatExtPowerStatsReply virtual method added through the callback
  chain (CommonCLI.h → MyMesh)
- formatExtPowerStats implementation in EnvironmentSensorManager that
  reads INA3221 channels
- CLI documentation update
pull/1797/head
MrAlders0n 4 months ago
parent
commit
d2b4733406
  1. 11
      docs/cli_commands.md
  2. 8
      examples/simple_repeater/MyMesh.cpp
  3. 1
      examples/simple_repeater/MyMesh.h
  4. 2
      src/helpers/CommonCLI.cpp
  5. 3
      src/helpers/CommonCLI.h
  6. 1
      src/helpers/SensorManager.h
  7. 25
      src/helpers/sensors/EnvironmentSensorManager.cpp
  8. 1
      src/helpers/sensors/EnvironmentSensorManager.h

11
docs/cli_commands.md

@ -127,6 +127,17 @@
---
### External Power Monitoring Stats - Per-channel voltage and current
**Usage:** `stats-extpower`
**Serial Only:** Yes
**Note:** Returns JSON with only enabled channels, e.g. `{"ch1_voltage_mv":12450,"ch1_current_ma":150,"ch2_voltage_mv":3800,"ch2_current_ma":85}`
**Note:** Returns "No external power monitoring board detected" if no supported hardware is present
---
## Logging
### Begin capture of rx log to node storage

8
examples/simple_repeater/MyMesh.cpp

@ -1015,10 +1015,16 @@ void MyMesh::formatRadioStatsReply(char *reply) {
}
void MyMesh::formatPacketStatsReply(char *reply) {
StatsFormatHelper::formatPacketStats(reply, radio_driver, getNumSentFlood(), getNumSentDirect(),
StatsFormatHelper::formatPacketStats(reply, radio_driver, getNumSentFlood(), getNumSentDirect(),
getNumRecvFlood(), getNumRecvDirect());
}
void MyMesh::formatExtPowerStatsReply(char *reply) {
if (!sensors.formatExtPowerStats(reply)) {
strcpy(reply, "No external power monitoring board detected");
}
}
void MyMesh::saveIdentity(const mesh::LocalIdentity &new_id) {
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
IdentityStore store(*_fs, "");

1
examples/simple_repeater/MyMesh.h

@ -207,6 +207,7 @@ public:
void formatStatsReply(char *reply) override;
void formatRadioStatsReply(char *reply) override;
void formatPacketStatsReply(char *reply) override;
void formatExtPowerStatsReply(char *reply) override;
mesh::LocalIdentity& getSelfId() override { return self_id; }

2
src/helpers/CommonCLI.cpp

@ -789,6 +789,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
_callbacks->formatRadioStatsReply(reply);
} else if (sender_timestamp == 0 && memcmp(command, "stats-core", 10) == 0 && (command[10] == 0 || command[10] == ' ')) {
_callbacks->formatStatsReply(reply);
} else if (sender_timestamp == 0 && memcmp(command, "stats-extpower", 14) == 0 && (command[14] == 0 || command[14] == ' ')) {
_callbacks->formatExtPowerStatsReply(reply);
} else {
strcpy(reply, "Unknown command");
}

3
src/helpers/CommonCLI.h

@ -75,6 +75,9 @@ public:
virtual void formatStatsReply(char *reply) = 0;
virtual void formatRadioStatsReply(char *reply) = 0;
virtual void formatPacketStatsReply(char *reply) = 0;
virtual void formatExtPowerStatsReply(char *reply) {
strcpy(reply, "No external power monitoring board detected");
};
virtual mesh::LocalIdentity& getSelfId() = 0;
virtual void saveIdentity(const mesh::LocalIdentity& new_id) = 0;
virtual void clearStats() = 0;

1
src/helpers/SensorManager.h

@ -23,6 +23,7 @@ public:
virtual const char* getSettingValue(int i) const { return NULL; }
virtual bool setSettingValue(const char* name, const char* value) { return false; }
virtual LocationProvider* getLocationProvider() { return NULL; }
virtual bool formatExtPowerStats(char* reply) { return false; }
// Helper functions to manage setting by keys (useful in many places ...)
const char* getSettingByKey(const char* key) {

25
src/helpers/sensors/EnvironmentSensorManager.cpp

@ -489,6 +489,31 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen
}
bool EnvironmentSensorManager::formatExtPowerStats(char* reply) {
#if ENV_INCLUDE_INA3221
if (!INA3221_initialized) return false;
char* dp = reply;
*dp++ = '{';
bool first = true;
for (int i = 0; i < TELEM_INA3221_NUM_CHANNELS; i++) {
if (INA3221.isChannelEnabled(i)) {
int ch = i + 1;
int voltage_mv = (int)(INA3221.getBusVoltage(i) * 1000);
int current_ma = (int)(INA3221.getCurrentAmps(i) * 1000);
if (!first) *dp++ = ',';
sprintf(dp, "\"ch%d_voltage_mv\":%d,\"ch%d_current_ma\":%d", ch, voltage_mv, ch, current_ma);
dp = strchr(dp, 0);
first = false;
}
}
*dp++ = '}';
*dp = 0;
return true;
#else
return false;
#endif
}
int EnvironmentSensorManager::getNumSettings() const {
int settings = 0;
#if ENV_INCLUDE_GPS

1
src/helpers/sensors/EnvironmentSensorManager.h

@ -55,4 +55,5 @@ public:
const char* getSettingName(int i) const override;
const char* getSettingValue(int i) const override;
bool setSettingValue(const char* name, const char* value) override;
bool formatExtPowerStats(char* reply) override;
};

Loading…
Cancel
Save