|
25 | 25 | import cros_ec_python.commands as ec_commands |
26 | 26 | import cros_ec_python.exceptions as ec_exceptions |
27 | 27 |
|
28 | | -@Gtk.Template(resource_path='/au/stevetech/yafi/ui/battery.ui') |
| 28 | + |
| 29 | +@Gtk.Template(resource_path="/au/stevetech/yafi/ui/battery.ui") |
29 | 30 | class BatteryPage(Gtk.Box): |
30 | | - __gtype_name__ = 'BatteryPage' |
| 31 | + __gtype_name__ = "BatteryPage" |
| 32 | + |
| 33 | + batt_status = Gtk.Template.Child() |
31 | 34 |
|
32 | | - chg_limit_enable = Gtk.Template.Child() |
33 | | - chg_limit = Gtk.Template.Child() |
34 | | - chg_limit_label = Gtk.Template.Child() |
35 | | - chg_limit_scale = Gtk.Template.Child() |
36 | | - bat_limit = Gtk.Template.Child() |
37 | | - bat_limit_label = Gtk.Template.Child() |
38 | | - bat_limit_scale = Gtk.Template.Child() |
39 | | - chg_limit_override = Gtk.Template.Child() |
40 | | - chg_limit_override_btn = Gtk.Template.Child() |
| 35 | + batt_charge = Gtk.Template.Child() |
| 36 | + batt_health = Gtk.Template.Child() |
| 37 | + batt_cycles_label = Gtk.Template.Child() |
| 38 | + batt_volts_label = Gtk.Template.Child() |
| 39 | + batt_watts_label = Gtk.Template.Child() |
| 40 | + batt_cap_rem_label = Gtk.Template.Child() |
| 41 | + batt_cap_full_label = Gtk.Template.Child() |
41 | 42 |
|
42 | | - bat_ext_group = Gtk.Template.Child() |
43 | | - bat_ext_enable = Gtk.Template.Child() |
44 | | - bat_ext_stage = Gtk.Template.Child() |
45 | | - bat_ext_trigger_time = Gtk.Template.Child() |
46 | | - bat_ext_reset_time = Gtk.Template.Child() |
47 | | - bat_ext_trigger = Gtk.Template.Child() |
48 | | - bat_ext_reset = Gtk.Template.Child() |
| 43 | + batt_manu = Gtk.Template.Child() |
| 44 | + batt_model = Gtk.Template.Child() |
| 45 | + batt_serial = Gtk.Template.Child() |
| 46 | + batt_type = Gtk.Template.Child() |
| 47 | + batt_orig_cap = Gtk.Template.Child() |
| 48 | + batt_orig_volts = Gtk.Template.Child() |
49 | 49 |
|
50 | 50 | def __init__(self, **kwargs): |
51 | 51 | super().__init__(**kwargs) |
52 | 52 |
|
53 | 53 | def setup(self, app): |
54 | | - # Charge limiter |
55 | | - try: |
56 | | - ec_limit = ec_commands.framework_laptop.get_charge_limit(app.cros_ec) |
57 | | - ec_limit_enabled = ec_limit != (0, 0) |
58 | | - self.chg_limit_enable.set_active(ec_limit_enabled) |
59 | | - if ec_limit_enabled: |
60 | | - self.chg_limit_scale.set_value(ec_limit[0]) |
61 | | - self.chg_limit_label.set_label(f"{ec_limit[0]}%") |
62 | | - self.bat_limit_scale.set_value(ec_limit[1]) |
63 | | - self.bat_limit_label.set_label(f"{ec_limit[1]}%") |
64 | | - self.chg_limit.set_sensitive(True) |
65 | | - self.bat_limit.set_sensitive(True) |
66 | | - self.chg_limit_override.set_sensitive(True) |
67 | | - |
68 | | - def handle_chg_limit_change(min, max): |
69 | | - ec_commands.framework_laptop.set_charge_limit( |
70 | | - app.cros_ec, int(min), int(max) |
71 | | - ) |
72 | | - |
73 | | - def handle_chg_limit_enable(switch): |
74 | | - active = switch.get_active() |
75 | | - if active: |
76 | | - handle_chg_limit_change( |
77 | | - self.chg_limit_scale.get_value(), self.bat_limit_scale.get_value() |
78 | | - ) |
79 | | - else: |
80 | | - ec_commands.framework_laptop.disable_charge_limit(app.cros_ec) |
81 | | - |
82 | | - self.chg_limit.set_sensitive(active) |
83 | | - self.bat_limit.set_sensitive(active) |
84 | | - self.chg_limit_override.set_sensitive(active) |
85 | | - |
86 | | - self.chg_limit_enable.connect( |
87 | | - "notify::active", lambda switch, _: handle_chg_limit_enable(switch) |
88 | | - ) |
89 | | - self.chg_limit_scale.connect( |
90 | | - "value-changed", |
91 | | - lambda scale: handle_chg_limit_change( |
92 | | - scale.get_value(), self.bat_limit_scale.get_value() |
93 | | - ), |
94 | | - ) |
95 | | - self.bat_limit_scale.connect( |
96 | | - "value-changed", |
97 | | - lambda scale: handle_chg_limit_change( |
98 | | - self.chg_limit_scale.get_value(), scale.get_value() |
99 | | - ), |
100 | | - ) |
101 | | - |
102 | | - self.chg_limit_override_btn.connect( |
103 | | - "clicked", |
104 | | - lambda _: ec_commands.framework_laptop.override_charge_limit( |
105 | | - app.cros_ec |
106 | | - ), |
107 | | - ) |
108 | | - except ec_exceptions.ECError as e: |
109 | | - if e.ec_status == ec_exceptions.EcStatus.EC_RES_INVALID_COMMAND: |
110 | | - app.no_support.append(ec_commands.framework_laptop.EC_CMD_CHARGE_LIMIT_CONTROL) |
111 | | - self.chg_limit_enable.set_sensitive(False) |
112 | | - else: |
113 | | - raise e |
114 | | - |
115 | | - # Battery Extender |
116 | | - try: |
117 | | - ec_extender = ec_commands.framework_laptop.get_battery_extender( |
118 | | - app.cros_ec |
119 | | - ) |
120 | | - self.bat_ext_enable.set_active(not ec_extender["disable"]) |
121 | | - self.bat_ext_stage.set_sensitive(not ec_extender["disable"]) |
122 | | - self.bat_ext_trigger_time.set_sensitive(not ec_extender["disable"]) |
123 | | - self.bat_ext_reset_time.set_sensitive(not ec_extender["disable"]) |
124 | | - self.bat_ext_trigger.set_sensitive(not ec_extender["disable"]) |
125 | | - self.bat_ext_reset.set_sensitive(not ec_extender["disable"]) |
126 | | - |
127 | | - self.bat_ext_stage.set_subtitle(str(ec_extender["current_stage"])) |
128 | | - self.bat_ext_trigger_time.set_subtitle( |
129 | | - format_timedelta(ec_extender["trigger_timedelta"]) |
130 | | - ) |
131 | | - self.bat_ext_reset_time.set_subtitle( |
132 | | - format_timedelta(ec_extender["reset_timedelta"]) |
133 | | - ) |
134 | | - self.bat_ext_trigger.set_value(ec_extender["trigger_days"]) |
135 | | - self.bat_ext_reset.set_value(ec_extender["reset_minutes"]) |
136 | | - |
137 | | - def handle_extender_enable(switch): |
138 | | - active = switch.get_active() |
139 | | - ec_commands.framework_laptop.set_battery_extender( |
140 | | - app.cros_ec, |
141 | | - not active, |
142 | | - int(self.bat_ext_trigger.get_value()), |
143 | | - int(self.bat_ext_reset.get_value()), |
144 | | - ) |
145 | | - self.bat_ext_stage.set_sensitive(active) |
146 | | - self.bat_ext_trigger_time.set_sensitive(active) |
147 | | - self.bat_ext_reset_time.set_sensitive(active) |
148 | | - self.bat_ext_trigger.set_sensitive(active) |
149 | | - self.bat_ext_reset.set_sensitive(active) |
150 | | - |
151 | | - self.bat_ext_enable.connect( |
152 | | - "notify::active", lambda switch, _: handle_extender_enable(switch) |
153 | | - ) |
154 | | - self.bat_ext_trigger.connect( |
155 | | - "notify::value", |
156 | | - lambda scale, _: ec_commands.framework_laptop.set_battery_extender( |
157 | | - app.cros_ec, |
158 | | - not self.bat_ext_enable.get_active(), |
159 | | - int(scale.get_value()), |
160 | | - int(self.bat_ext_reset.get_value()), |
161 | | - ), |
162 | | - ) |
163 | | - self.bat_ext_reset.connect( |
164 | | - "notify::value", |
165 | | - lambda scale, _: ec_commands.framework_laptop.set_battery_extender( |
166 | | - app.cros_ec, |
167 | | - not self.bat_ext_enable.get_active(), |
168 | | - int(self.bat_ext_trigger.get_value()), |
169 | | - int(scale.get_value()), |
170 | | - ), |
171 | | - ) |
172 | | - except ec_exceptions.ECError as e: |
173 | | - if e.ec_status == ec_exceptions.EcStatus.EC_RES_INVALID_COMMAND: |
174 | | - app.no_support.append( |
175 | | - ec_commands.framework_laptop.EC_CMD_BATTERY_EXTENDER |
176 | | - ) |
177 | | - self.bat_ext_group.set_visible(False) |
178 | | - else: |
179 | | - raise e |
180 | | - |
| 54 | + battery = ec_commands.memmap.get_battery_values(app.cros_ec) |
| 55 | + self.batt_manu.set_subtitle(battery["manufacturer"]) |
| 56 | + self.batt_model.set_subtitle(battery["model"]) |
| 57 | + self.batt_serial.set_subtitle(battery["serial"]) |
| 58 | + self.batt_type.set_subtitle(battery["type"]) |
| 59 | + self.batt_orig_cap.set_subtitle(f"{self._get_watts(battery, 'design_capacity'):.2f}Wh") |
| 60 | + self.batt_orig_volts.set_subtitle(f"{battery['design_voltage']/1000}V") |
| 61 | + self._update_battery(app, battery) |
181 | 62 | # Schedule _update_battery to run every second |
182 | | - GLib.timeout_add_seconds( |
183 | | - 1, |
184 | | - self._update_battery, |
185 | | - app |
| 63 | + GLib.timeout_add_seconds(1, self._update_battery, app) |
| 64 | + |
| 65 | + def _get_watts(self, battery, key, volt_key="design_voltage"): |
| 66 | + return (battery[key] * battery[volt_key]) / 1000_000 |
| 67 | + |
| 68 | + def _update_battery(self, app, battery=None): |
| 69 | + if battery is None: |
| 70 | + battery = ec_commands.memmap.get_battery_values(app.cros_ec) |
| 71 | + |
| 72 | + status_messages = [] |
| 73 | + if battery["invalid_data"]: |
| 74 | + status_messages.append("Invalid Data") |
| 75 | + if not battery["batt_present"]: |
| 76 | + status_messages.append("No Battery") |
| 77 | + if battery["ac_present"]: |
| 78 | + status_messages.append("Plugged in") |
| 79 | + if battery["level_critical"]: |
| 80 | + status_messages.append("Critical") |
| 81 | + if battery["discharging"]: |
| 82 | + status_messages.append("Discharging") |
| 83 | + if battery["charging"]: |
| 84 | + status_messages.append("Charging") |
| 85 | + self.batt_status.set_subtitle(", ".join(status_messages)) |
| 86 | + |
| 87 | + self.batt_charge.set_fraction( |
| 88 | + battery["capacity"] / battery["last_full_charge_capacity"] |
| 89 | + ) |
| 90 | + self.batt_health.set_fraction( |
| 91 | + battery["last_full_charge_capacity"] / battery["design_capacity"] |
| 92 | + ) |
| 93 | + self.batt_cycles_label.set_label(str(battery["cycle_count"])) |
| 94 | + self.batt_volts_label.set_label(f"{battery['volt']/1000:.2f}V") |
| 95 | + self.batt_watts_label.set_label( |
| 96 | + f"{self._get_watts(battery, 'rate', 'volt') * (-1 if battery['charging'] else 1):.2f}W" |
| 97 | + ) |
| 98 | + self.batt_cap_rem_label.set_label( |
| 99 | + f"{self._get_watts(battery, 'capacity'):.2f}Wh" |
| 100 | + ) |
| 101 | + self.batt_cap_full_label.set_label( |
| 102 | + f"{self._get_watts(battery, 'last_full_charge_capacity'):.2f}Wh" |
186 | 103 | ) |
187 | 104 |
|
188 | | - def _update_battery(self, app): |
189 | | - success = False |
190 | | - |
191 | | - # Charge Limiter |
192 | | - if not ec_commands.framework_laptop.EC_CMD_CHARGE_LIMIT_CONTROL in app.no_support: |
193 | | - try: |
194 | | - ec_limit = ec_commands.framework_laptop.get_charge_limit(app.cros_ec) |
195 | | - self.chg_limit_label.set_label(f"{ec_limit[0]}%") |
196 | | - self.bat_limit_label.set_label(f"{ec_limit[1]}%") |
197 | | - |
198 | | - success = True |
199 | | - except ec_exceptions.ECError as e: |
200 | | - if e.ec_status == ec_exceptions.EcStatus.EC_RES_INVALID_COMMAND: |
201 | | - app.no_support.append(ec_commands.framework_laptop.EC_CMD_CHARGE_LIMIT_CONTROL) |
202 | | - else: |
203 | | - raise e |
204 | | - |
205 | | - # Battery Extender |
206 | | - if not ec_commands.framework_laptop.EC_CMD_BATTERY_EXTENDER in app.no_support: |
207 | | - try: |
208 | | - ec_extender = ec_commands.framework_laptop.get_battery_extender( |
209 | | - app.cros_ec |
210 | | - ) |
211 | | - |
212 | | - self.bat_ext_stage.set_subtitle(str(ec_extender["current_stage"])) |
213 | | - self.bat_ext_trigger_time.set_subtitle( |
214 | | - format_timedelta(ec_extender["trigger_timedelta"]) |
215 | | - ) |
216 | | - self.bat_ext_reset_time.set_subtitle( |
217 | | - format_timedelta(ec_extender["reset_timedelta"]) |
218 | | - ) |
219 | | - |
220 | | - success = True |
221 | | - except ec_exceptions.ECError as e: |
222 | | - if e.ec_status == ec_exceptions.EcStatus.EC_RES_INVALID_COMMAND: |
223 | | - app.no_support.append( |
224 | | - ec_commands.framework_laptop.EC_CMD_BATTERY_EXTENDER |
225 | | - ) |
226 | | - else: |
227 | | - raise e |
228 | | - |
229 | | - return app.current_page == 2 and success |
230 | | - |
231 | | -def format_timedelta(timedelta): |
232 | | - days = f"{timedelta.days} days, " if timedelta.days else "" |
233 | | - hours, remainder = divmod(timedelta.seconds, 3600) |
234 | | - minutes, seconds = divmod(remainder, 60) |
235 | | - return days + f"{hours}:{minutes:02}:{seconds:02}" |
| 105 | + return app.current_page == 2 |
0 commit comments