Skip to content

Commit d2b4733

Browse files
committed
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
1 parent d05d6ab commit d2b4733

8 files changed

Lines changed: 51 additions & 1 deletion

File tree

docs/cli_commands.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,17 @@
127127

128128
---
129129

130+
### External Power Monitoring Stats - Per-channel voltage and current
131+
**Usage:** `stats-extpower`
132+
133+
**Serial Only:** Yes
134+
135+
**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}`
136+
137+
**Note:** Returns "No external power monitoring board detected" if no supported hardware is present
138+
139+
---
140+
130141
## Logging
131142

132143
### Begin capture of rx log to node storage

examples/simple_repeater/MyMesh.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,10 +1015,16 @@ void MyMesh::formatRadioStatsReply(char *reply) {
10151015
}
10161016

10171017
void MyMesh::formatPacketStatsReply(char *reply) {
1018-
StatsFormatHelper::formatPacketStats(reply, radio_driver, getNumSentFlood(), getNumSentDirect(),
1018+
StatsFormatHelper::formatPacketStats(reply, radio_driver, getNumSentFlood(), getNumSentDirect(),
10191019
getNumRecvFlood(), getNumRecvDirect());
10201020
}
10211021

1022+
void MyMesh::formatExtPowerStatsReply(char *reply) {
1023+
if (!sensors.formatExtPowerStats(reply)) {
1024+
strcpy(reply, "No external power monitoring board detected");
1025+
}
1026+
}
1027+
10221028
void MyMesh::saveIdentity(const mesh::LocalIdentity &new_id) {
10231029
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
10241030
IdentityStore store(*_fs, "");

examples/simple_repeater/MyMesh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
207207
void formatStatsReply(char *reply) override;
208208
void formatRadioStatsReply(char *reply) override;
209209
void formatPacketStatsReply(char *reply) override;
210+
void formatExtPowerStatsReply(char *reply) override;
210211

211212
mesh::LocalIdentity& getSelfId() override { return self_id; }
212213

src/helpers/CommonCLI.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
789789
_callbacks->formatRadioStatsReply(reply);
790790
} else if (sender_timestamp == 0 && memcmp(command, "stats-core", 10) == 0 && (command[10] == 0 || command[10] == ' ')) {
791791
_callbacks->formatStatsReply(reply);
792+
} else if (sender_timestamp == 0 && memcmp(command, "stats-extpower", 14) == 0 && (command[14] == 0 || command[14] == ' ')) {
793+
_callbacks->formatExtPowerStatsReply(reply);
792794
} else {
793795
strcpy(reply, "Unknown command");
794796
}

src/helpers/CommonCLI.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ class CommonCLICallbacks {
7575
virtual void formatStatsReply(char *reply) = 0;
7676
virtual void formatRadioStatsReply(char *reply) = 0;
7777
virtual void formatPacketStatsReply(char *reply) = 0;
78+
virtual void formatExtPowerStatsReply(char *reply) {
79+
strcpy(reply, "No external power monitoring board detected");
80+
};
7881
virtual mesh::LocalIdentity& getSelfId() = 0;
7982
virtual void saveIdentity(const mesh::LocalIdentity& new_id) = 0;
8083
virtual void clearStats() = 0;

src/helpers/SensorManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class SensorManager {
2323
virtual const char* getSettingValue(int i) const { return NULL; }
2424
virtual bool setSettingValue(const char* name, const char* value) { return false; }
2525
virtual LocationProvider* getLocationProvider() { return NULL; }
26+
virtual bool formatExtPowerStats(char* reply) { return false; }
2627

2728
// Helper functions to manage setting by keys (useful in many places ...)
2829
const char* getSettingByKey(const char* key) {

src/helpers/sensors/EnvironmentSensorManager.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,31 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen
489489
}
490490

491491

492+
bool EnvironmentSensorManager::formatExtPowerStats(char* reply) {
493+
#if ENV_INCLUDE_INA3221
494+
if (!INA3221_initialized) return false;
495+
char* dp = reply;
496+
*dp++ = '{';
497+
bool first = true;
498+
for (int i = 0; i < TELEM_INA3221_NUM_CHANNELS; i++) {
499+
if (INA3221.isChannelEnabled(i)) {
500+
int ch = i + 1;
501+
int voltage_mv = (int)(INA3221.getBusVoltage(i) * 1000);
502+
int current_ma = (int)(INA3221.getCurrentAmps(i) * 1000);
503+
if (!first) *dp++ = ',';
504+
sprintf(dp, "\"ch%d_voltage_mv\":%d,\"ch%d_current_ma\":%d", ch, voltage_mv, ch, current_ma);
505+
dp = strchr(dp, 0);
506+
first = false;
507+
}
508+
}
509+
*dp++ = '}';
510+
*dp = 0;
511+
return true;
512+
#else
513+
return false;
514+
#endif
515+
}
516+
492517
int EnvironmentSensorManager::getNumSettings() const {
493518
int settings = 0;
494519
#if ENV_INCLUDE_GPS

src/helpers/sensors/EnvironmentSensorManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,5 @@ class EnvironmentSensorManager : public SensorManager {
5555
const char* getSettingName(int i) const override;
5656
const char* getSettingValue(int i) const override;
5757
bool setSettingValue(const char* name, const char* value) override;
58+
bool formatExtPowerStats(char* reply) override;
5859
};

0 commit comments

Comments
 (0)