| 1 |
const std = @import("std");
|
| 2 |
const format_util = @import("format.zig");
|
| 3 |
|
| 4 |
pub const Battery = struct {
|
| 5 |
format_charging: []const u8,
|
| 6 |
format_discharging: []const u8,
|
| 7 |
format_full: []const u8,
|
| 8 |
battery_name: []const u8,
|
| 9 |
interval_secs: u64,
|
| 10 |
color: c_ulong,
|
| 11 |
|
| 12 |
pub fn init(
|
| 13 |
format_charging: []const u8,
|
| 14 |
format_discharging: []const u8,
|
| 15 |
format_full: []const u8,
|
| 16 |
battery_name: []const u8,
|
| 17 |
interval_secs: u64,
|
| 18 |
color: c_ulong,
|
| 19 |
) Battery {
|
| 20 |
return .{
|
| 21 |
.format_charging = format_charging,
|
| 22 |
.format_discharging = format_discharging,
|
| 23 |
.format_full = format_full,
|
| 24 |
.battery_name = if (battery_name.len > 0) battery_name else "BAT0",
|
| 25 |
.interval_secs = interval_secs,
|
| 26 |
.color = color,
|
| 27 |
};
|
| 28 |
}
|
| 29 |
|
| 30 |
pub fn content(self: *Battery, buffer: []u8) []const u8 {
|
| 31 |
var path_buf: [128]u8 = undefined;
|
| 32 |
|
| 33 |
const capacity = self.read_battery_file(&path_buf, "capacity") orelse return buffer[0..0];
|
| 34 |
const status = self.read_battery_status(&path_buf) orelse return buffer[0..0];
|
| 35 |
|
| 36 |
const format = switch (status) {
|
| 37 |
.charging => self.format_charging,
|
| 38 |
.discharging => self.format_discharging,
|
| 39 |
.full => self.format_full,
|
| 40 |
};
|
| 41 |
|
| 42 |
var cap_buf: [8]u8 = undefined;
|
| 43 |
const cap_str = std.fmt.bufPrint(&cap_buf, "{d}", .{capacity}) catch return buffer[0..0];
|
| 44 |
|
| 45 |
return format_util.substitute(format, cap_str, buffer);
|
| 46 |
}
|
| 47 |
|
| 48 |
const Status = enum { charging, discharging, full };
|
| 49 |
|
| 50 |
fn read_battery_status(self: *Battery, path_buf: *[128]u8) ?Status {
|
| 51 |
const path = std.fmt.bufPrint(path_buf, "/sys/class/power_supply/{s}/status", .{self.battery_name}) catch return null;
|
| 52 |
|
| 53 |
const file = std.fs.openFileAbsolute(path, .{}) catch return null;
|
| 54 |
defer file.close();
|
| 55 |
|
| 56 |
var buf: [32]u8 = undefined;
|
| 57 |
const len = file.read(&buf) catch return null;
|
| 58 |
const status_str = std.mem.trim(u8, buf[0..len], " \n\r\t");
|
| 59 |
|
| 60 |
if (std.mem.eql(u8, status_str, "Charging")) return .charging;
|
| 61 |
if (std.mem.eql(u8, status_str, "Discharging")) return .discharging;
|
| 62 |
if (std.mem.eql(u8, status_str, "Full")) return .full;
|
| 63 |
if (std.mem.eql(u8, status_str, "Not charging")) return .full;
|
| 64 |
return .discharging;
|
| 65 |
}
|
| 66 |
|
| 67 |
fn read_battery_file(self: *Battery, path_buf: *[128]u8, file_name: []const u8) ?u8 {
|
| 68 |
const path = std.fmt.bufPrint(path_buf, "/sys/class/power_supply/{s}/{s}", .{ self.battery_name, file_name }) catch return null;
|
| 69 |
|
| 70 |
const file = std.fs.openFileAbsolute(path, .{}) catch return null;
|
| 71 |
defer file.close();
|
| 72 |
|
| 73 |
var buf: [16]u8 = undefined;
|
| 74 |
const len = file.read(&buf) catch return null;
|
| 75 |
const value_str = std.mem.trim(u8, buf[0..len], " \n\r\t");
|
| 76 |
|
| 77 |
return std.fmt.parseInt(u8, value_str, 10) catch null;
|
| 78 |
}
|
| 79 |
|
| 80 |
pub fn interval(self: *Battery) u64 {
|
| 81 |
return self.interval_secs;
|
| 82 |
}
|
| 83 |
|
| 84 |
pub fn get_color(self: *Battery) c_ulong {
|
| 85 |
return self.color;
|
| 86 |
}
|
| 87 |
};
|