summaryrefslogtreecommitdiff
path: root/lib/battery/device.vala
blob: db695748187a7ba89dbcb629942ace4860c7b426 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
namespace AstalBattery {
    /** Get the DisplayDevice. */
    public Device get_default() {
        return Device.get_default();
    }
}

/**
 * Client for a UPower [[https://upower.freedesktop.org/docs/Device.html|device]].
 */
public class AstalBattery.Device : Object {
    private static Device display_device;

    /** Get the DisplayDevice. */
    public static Device? get_default() {
        if (display_device != null) {
            return display_device;
        }

        try {
            display_device = new Device((ObjectPath)"/org/freedesktop/UPower/devices/DisplayDevice");
            return display_device;
        } catch (Error error) {
            critical(error.message);
        }

        return null;
    }

    private IUPowerDevice proxy;

    public Device(ObjectPath path) throws Error {
        proxy = Bus.get_proxy_sync(BusType.SYSTEM, "org.freedesktop.UPower", path);
        proxy.g_properties_changed.connect(sync);
        sync();
    }

    /**
     * If it is [[email protected]], you will need to verify that the
     * property power-supply has the value `true` before considering it as a laptop battery.
     * Otherwise it will likely be the battery for a device of an unknown type.
     */
    public Type device_type { get; private set; }

    /**
     * Native path of the power source. This is the sysfs path,
     * for example /sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/power_supply/BAT0.
     * It is blank if the device is being driven by a user space driver.
     */
    public string native_path { owned get; private set; }

    /** Name of the vendor of the battery. */
    public string vendor { owned get; private set; }

    /** Name of the model of this battery. */
    public string model { owned get; private set; }

    /** Unique serial number of the battery. */
    public string serial { owned get; private set; }

    /**
     * The point in time (seconds since the Epoch)
     * that data was read from the power source.
     */
    public uint64 update_time { get; private set; }

    /**
     * If the power device is used to supply the system.
     * This would be set `true` for laptop batteries and UPS devices,
     * but set to `false` for wireless mice or PDAs.
     */
    public bool power_supply { get; private set; }

    /** If the power device has history. */
    // TODO: public bool has_history { get; private set; }

    /** If the power device has statistics. */
    // TODO: public bool has_statistics { get; private set; }

    /**
     * Whether power is currently being provided through line power.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]_POWER].
     */
    public bool online { get; private set; }

    /**
     * Amount of energy (measured in Wh) currently available in the power source.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public double energy { get; private set; }

    /**
     * Amount of energy (measured in Wh) in the power source when it's considered to be empty.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public double energy_empty { get; private set; }

    /**
     * Amount of energy (measured in Wh) in the power source when it's considered full.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public double energy_full { get; private set; }

    /**
     * Amount of energy (measured in Wh) the power source is designed to hold when it's considered full.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public double energy_full_design { get; private set; }

    /**
     * Amount of energy being drained from the source, measured in W.
     * If positive, the source is being discharged, if negative it's being charged.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public double energy_rate { get; private set; }

    /** Voltage in the Cell or being recorded by the meter. */
    public double voltage { get; private set; }

    /**
     * The number of charge cycles as defined by the TCO certification,
     * or -1 if that value is unknown or not applicable.
     */
    public int charge_cycles { get; private set; }

    /** Luminosity being recorded by the meter. */
    public double luminosity { get; private set; }

    /**
     * Number of seconds until the power source is considered empty. Is set to 0 if unknown.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public int64 time_to_empty { get; private set; }

    /**
     * Number of seconds until the power source is considered full. Is set to 0 if unknown.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public int64 time_to_full { get; private set;}

    /**
     * The amount of energy left in the power source expressed as a percentage between 0 and 1.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     * The percentage will be an approximation if [[email protected]:battery_level]
     * is set to something other than None.
     */
    public double percentage { get; private set; }

    /**
     * The temperature of the device in degrees Celsius.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public double temperature { get; private set; }

    /**
     * If the power source is present in the bay.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public bool is_present { get; private set; }

    /**
     * The battery power state.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public State state { get; private set; }

    /**
     * If the power source is rechargeable.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public bool is_rechargable { get; private set; }

    /**
     * The capacity of the power source expressed as a percentage between 0 and 1.
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public double capacity { get; private set; }

    /**
     * Technology used in the battery:
     *
     * This property is only valid if [[email protected]:device_type] is [[email protected]].
     */
    public Technology technology { get; private set; }

    /** Warning level of the battery. */
    public WarningLevel warning_level { get; private set; }

    /**
     * The level of the battery for devices which do not report a percentage
     * but rather a coarse battery level. If the value is None.
     * then the device does not support coarse battery reporting,
     * and the [[email protected]:percentage] should be used instead.
     */
    public BatteryLevel battery_level { get; private set; }

    /**
     * An icon name representing this Device.
     *
     * NOTE: [[email protected]:battery_icon_name] might be a better fit
     * as it is calculated from percentage.
     */
    public string icon_name { owned get; private set; }

    /**
     * Indicates if [[email protected]:state] is charging or fully charged.
     */
    public bool charging { get; private set; }

    /**
     * Indicates if [[email protected]:device_type] is not line power or unknown.
     */
    public bool is_battery { get; private set; }

    /**
     * An icon name in the form of "battery-level-$percentage-$state-symbolic".
     */
    public string battery_icon_name { get; private set; }

    /**
     * A string representation of this device's [[email protected]:device_type].
     */
    public string device_type_name { get; private set; }

    /**
     * An icon name that can be used to represent this device's [[email protected]:device_type].
     */
    public string device_type_icon { get; private set; }

    // TODO: get_history
    // TODO: get_statistics

    private void sync() {
        device_type = (Type)proxy.Type;
        native_path = proxy.native_path;
        vendor = proxy.vendor;
        model = proxy.model;
        serial = proxy.serial;
        update_time = proxy.update_time;
        power_supply = proxy.power_supply;
        // TODO: has_history = proxy.has_history;
        // TODO: has_statistics = proxy.has_statistics;
        online = proxy.online;
        energy = proxy.energy;
        energy_empty = proxy.energy_empty;
        energy_full = proxy.energy_full;
        energy_full_design = proxy.energy_full_design;
        energy_rate = proxy.energy_rate;
        voltage = proxy.voltage;
        charge_cycles = proxy.charge_cycles;
        luminosity = proxy.luminosity;
        time_to_empty = proxy.time_to_empty;
        time_to_full = proxy.time_to_full;
        percentage = proxy.percentage / 100;
        temperature = proxy.temperature;
        is_present = proxy.is_present;
        state = (State)proxy.state;
        is_rechargable = proxy.is_rechargable;
        capacity = proxy.capacity / 100;
        technology = (Technology)proxy.technology;
        warning_level = (WarningLevel)proxy.warning_level;
        battery_level = (BatteryLevel)proxy.battery_level;
        icon_name = proxy.icon_name;

        charging = state == State.FULLY_CHARGED || state == State.CHARGING;
        is_battery = device_type != Type.UNKNOWN && device_type != Type.LINE_POWER;

        if (!is_battery) {
            battery_icon_name = "battery-missing-symbolic";
        } else if (percentage >= 0.95 && charging) {
            battery_icon_name = "battery-level-100-charged-symbolic";
        } else {
            var state = charging ? "-charging" : "";
            var level = (int)Math.round(percentage * 10)*10;
            battery_icon_name = @"battery-level-$level$state-symbolic";
        }

        device_type_name = device_type.get_name();
        device_type_icon = device_type.get_icon_name();
    }
}

[CCode (type_signature = "u")]
public enum AstalBattery.State {
    UNKNOWN,
    CHARGING,
    DISCHARGING,
    EMPTY,
    FULLY_CHARGED,
    PENDING_CHARGE,
    PENDING_DISCHARGE,
}

[CCode (type_signature = "u")]
public enum AstalBattery.Technology {
    UNKNOWN,
    LITHIUM_ION,
    LITHIUM_POLYMER,
    LITHIUM_IRON_PHOSPHATE,
    LEAD_ACID,
    NICKEL_CADMIUM,
    NICKEL_METAL_HYDRIDE,
}

[CCode (type_signature = "u")]
public enum AstalBattery.WarningLevel {
    UNKNOWN,
    NONE,
    DISCHARGING,
    LOW,
    CRITICIAL,
    ACTION,
}

[CCode (type_signature = "u")]
public enum AstalBattery.BatteryLevel {
    UNKNOWN,
    NONE,
    LOW,
    CRITICIAL,
    NORMAL,
    HIGH,
    FULL,
}

[CCode (type_signature = "u")]
public enum AstalBattery.Type {
    UNKNOWN,
    LINE_POWER,
    BATTERY,
    UPS,
    MONITOR,
    MOUSE,
    KEYBOARD,
    PDA,
    PHONE,
    MEDIA_PLAYER,
    TABLET,
    COMPUTER,
    GAMING_INPUT,
    PEN,
    TOUCHPAD,
    MODEM,
    NETWORK,
    HEADSET,
    SPEAKERS,
    HEADPHONES,
    VIDEO,
    OTHER_AUDIO,
    REMOVE_CONTROL,
    PRINTER,
    SCANNER,
    CAMERA,
    WEARABLE,
    TOY,
    BLUETOOTH_GENERIC;

    // TODO: add more icon names
    internal string? get_icon_name () {
        switch (this) {
            case UPS:
                return "uninterruptible-power-supply";
            case MOUSE:
                return "input-mouse";
            case KEYBOARD:
                return "input-keyboard";
            case PDA:
            case PHONE:
                return "phone";
            case MEDIA_PLAYER:
                return "multimedia-player";
            case TABLET:
            case PEN:
                return "input-tablet";
            case GAMING_INPUT:
                return "input-gaming";
            default:
                return null;
        }
    }

    internal unowned string? get_name () {
        switch (this) {
            case LINE_POWER:
                return "Plugged In";
            case BATTERY:
                return "Battery";
            case UPS:
                return "UPS";
            case MONITOR:
                return "Display";
            case MOUSE:
                return "Mouse";
            case KEYBOARD:
                return "Keyboard";
            case PDA:
                return "PDA";
            case PHONE:
                return "Phone";
            case MEDIA_PLAYER:
                return "Media Player";
            case TABLET:
                return "Tablet";
            case COMPUTER:
                return "Computer";
            case GAMING_INPUT:
                return "Controller";
            case PEN:
                return "Pen";
            case TOUCHPAD:
                return "Touchpad";
            case MODEM:
                return "Modem";
            case NETWORK:
                return "Network";
            case HEADSET:
                return "Headset";
            case SPEAKERS:
                return "Speakers";
            case HEADPHONES:
                return "Headphones";
            case VIDEO:
                return "Video";
            case OTHER_AUDIO:
                return "Other Audio";
            case REMOVE_CONTROL:
                return "Remove Control";
            case PRINTER:
                return "Printer";
            case SCANNER:
                return "Scanner";
            case CAMERA:
                return "Camera";
            case WEARABLE:
                return "Wearable";
            case TOY:
                return "Toy";
            case BLUETOOTH_GENERIC:
                return "Bluetooth Generic";
            default:
                return "Unknown";
        }
    }
}