@@ -43,21 +43,124 @@ static void BatteryMeter_updateValues(Meter* this) {
4343
4444 this -> values [0 ] = info .percent ;
4545
46- const char * text ;
47- switch (info .ac ) {
48- case AC_PRESENT :
49- text = this -> mode == TEXT_METERMODE ? " (Running on A/C)" : "(A/C)" ;
50- break ;
51- case AC_ABSENT :
52- text = this -> mode == TEXT_METERMODE ? " (Running on battery)" : "(bat)" ;
53- break ;
54- case AC_ERROR :
55- default :
56- text = "" ;
57- break ;
46+ bool haveEnergy = isNonnegative (info .energyCurr ) && isNonnegative (info .energyFull );
47+
48+ /* Without energy data there is nothing useful to show beyond the percent. */
49+ if (!haveEnergy ) {
50+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "%.1f%%" , info .percent );
51+ return ;
52+ }
53+
54+ bool havePower = isfinite (info .powerCurr );
55+
56+ /* stable: power unknown or |power| < 5 W – time estimate would be unreliable */
57+ bool isDischarging = havePower && info .powerCurr <= -5.0 ;
58+ bool isCharging = havePower && info .powerCurr >= 5.0 ;
59+
60+ /* time estimate in whole minutes; -1 means not available */
61+ int timeMinutes = -1 ;
62+ if (isDischarging && isPositive (info .energyCurr )) {
63+ /* floor for discharge; powerCurr is negative, use negative scaling when dividing */
64+ timeMinutes = (int )floor (info .energyCurr / info .powerCurr * -60.0 );
65+ } else if (isCharging && 0.95 * info .energyFull > info .energyCurr ) {
66+ /* ceil for charge */
67+ timeMinutes = (int )ceil ((0.95 * info .energyFull - info .energyCurr ) / info .powerCurr * 60.0 );
68+ }
69+
70+ char * buf = this -> txtBuffer ;
71+ size_t len = sizeof (this -> txtBuffer );
72+ int ret = 0 ;
73+
74+ if (this -> mode == TEXT_METERMODE ) {
75+ if (info .ac == AC_PRESENT ) {
76+ ret = xSnprintf (buf , len , "Using %s" , isDischarging ? "AC+bat" : "AC" );
77+ buf += ret ; len -= ret ;
78+ } else if (info .ac == AC_ABSENT ) {
79+ ret = xSnprintf (buf , len , "Using bat" );
80+ buf += ret ; len -= ret ;
81+ }
82+
83+ if (ret && len > 2 ) {
84+ * buf ++ = ',' ;
85+ * buf ++ = ' ' ;
86+ * buf = 0 ;
87+ len -= 2 ;
88+ }
89+
90+ if (isDischarging ) {
91+ ret = xSnprintf (
92+ buf , len , "discharging at %.1fW, %.1f/%.1fWh (%.1f%%)" ,
93+ - info .powerCurr , info .energyCurr , info .energyFull , info .percent
94+ );
95+ buf += ret ; len -= ret ;
96+ if (timeMinutes >= 0 ) {
97+ ret = xSnprintf (buf , len , ", time remaining: %dh%02dm" , timeMinutes / 60 , timeMinutes % 60 );
98+ buf += ret ; len -= ret ;
99+ }
100+ } else if (isCharging ) {
101+ ret = xSnprintf (
102+ buf , len , "charging at %.1fW, %.1f/%.1fWh (%.1f%%)" ,
103+ info .powerCurr , info .energyCurr , info .energyFull , info .percent
104+ );
105+ buf += ret ; len -= ret ;
106+
107+ if (timeMinutes >= 0 ) {
108+ ret = xSnprintf (
109+ buf , len , ", time to full: %dh%02dm" ,
110+ timeMinutes / 60 , timeMinutes % 60
111+ );
112+ buf += ret ; len -= ret ;
113+ }
114+ } else {
115+ ret = xSnprintf (
116+ buf , len , "stable at %.1f/%.1fWh (%.1f%%)" ,
117+ info .energyCurr , info .energyFull , info .percent
118+ );
119+ buf += ret ; len -= ret ;
120+ }
121+ } else {
122+ /* compact label for bar / graph modes */
123+ if (info .ac == AC_PRESENT ) {
124+ ret = xSnprintf (buf , len , "%s" , isDischarging ? "AC+bat" : "AC" );
125+ buf += ret ; len -= ret ;
126+ } else if (info .ac == AC_ABSENT ) {
127+ ret = xSnprintf (buf , len , "bat" );
128+ buf += ret ; len -= ret ;
129+ }
130+
131+ if (ret && len > 1 ) {
132+ * buf ++ = ' ' ;
133+ * buf = 0 ;
134+ len -- ;
135+ }
136+
137+ if (isCharging || isDischarging ) {
138+ ret = xSnprintf (
139+ buf , len , "%+.1fW @ %.1f/%.1fWh" ,
140+ info .powerCurr , info .energyCurr , info .energyFull
141+ );
142+ buf += ret ; len -= ret ;
143+
144+ if (timeMinutes >= 0 ) {
145+ ret = xSnprintf (
146+ buf , len , ", %dh%02dm" ,
147+ timeMinutes / 60 , timeMinutes % 60
148+ );
149+ buf += ret ; len -= ret ;
150+ }
151+ } else {
152+ ret = xSnprintf (
153+ buf , len , "stable @ %.1f/%.1fWh" ,
154+ info .energyCurr , info .energyFull
155+ );
156+ buf += ret ; len -= ret ;
157+ }
58158 }
59159
60- xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "%.1f%%%s" , info .percent , text );
160+ // Simplify the pattern to always use "buf += ret; len -= ret;" for all cases
161+ (void )ret ;
162+ (void )buf ;
163+ (void )len ;
61164}
62165
63166const MeterClass BatteryMeter_class = {
0 commit comments