Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement power supply and disk #20

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions spec/power/battery_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require "spec"
require "../../src/power_supply/battery"

battery_exists = false

begin
Hardware::Battery.new_single
battery_exists = true
rescue
end

if battery_exists
describe Hardware::Battery do
battery = Hardware::Battery.new_single

it "checks the `type` type" do
battery.type.should be_a Hardware::PowerSupply::Type
end

it "checks the `capacity` type" do
battery.capacity.should be_a UInt8
end

it "checks the `status` type" do
battery.status.should be_a Hardware::Battery::Status
end
end
end
32 changes: 32 additions & 0 deletions spec/power_supply_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require "spec"
require "../src/power_supply"

battery_exists = false

begin
Hardware::Battery.new_single
battery_exists = true
rescue
end

if battery_exists
describe Hardware::PowerSupply do
power = Hardware::Battery.new_single

it "checks the `type` type" do
power.type.should be_a Hardware::PowerSupply::Type
end

it "checks the `serial_number` type" do
power.serial_number.should be_a String
end

it "checks the `model_name` type" do
power.model_name.should be_a String
end

it "checks the `manufacturer` type" do
power.manufacturer.should be_a String
end
end
end
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved
59 changes: 59 additions & 0 deletions src/power_supply.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Power supply related informations
#
# ```
# # Run the command below to manually find the device available
# # `ls /sys/class/power_supply/`
# power_supply = Hardware::PowerSupply.new("BAT0") # Specify the batery device name by yourself
# ```
class Hardware::PowerSupply
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use abstract struct because:

  • this objects are immutable
  • we usually want to use Hardware::Battery instead of Hardware::PowerSupply if we have a battery.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, a dedicated error type can be created inside like:

class Error < Exception
end

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use abstract struct because:

  • this objects are immutable
  • we usually want to use Hardware::Battery instead of Hardware::PowerSupply if we have a battery.

I'm using class because it allows me to use inheritance and to define Hardware::PowerSupply as non abstract so it may be used

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why one would use PowerSupply directly, because it is either a UPS, Battery, Main or USB.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After I think it again, PowerSupply is not necessary to be used directly. I have made it into an abstract struct..

DEVICE_DIRECTORY = "/sys/class/power_supply"
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved

@current_device_path : Path

enum Type : UInt8
Battery
UPS
Mains
USB
end
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved

def initialize(supply_name : String)
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved
@current_device_path = Path.new("#{DEVICE_DIRECTORY}/#{supply_name}")
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved
end

# Get entries of the available device
def self.entries
Dir.entries(DEVICE_DIRECTORY).reject { |filename| filename.starts_with?('.') }
end
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved

record EntryType, name : String, type : Type

# Get entries of the available device with the device type
def self.entries_with_type
self.entries.reduce([] of EntryType) do |entries, filename|
entries << EntryType.new(filename, PowerSupply.new(filename).type)
end
end
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved

# Describes the main type of the supply
# It can be Battery, UPS, Mains, or USB. See Hardware::PowerSupply::Type
def type : Type
content = File.read(@current_device_path / "type").rstrip
Type.parse?(content).not_nil!
end
j8r marked this conversation as resolved.
Show resolved Hide resolved

# Reports the serial number of the device
def serial_number : String
File.read(@current_device_path / "serial_number").rstrip
end

# Reports the name of the device model
def model_name : String
File.read(@current_device_path / "model_name").rstrip
end

# Reports the name of the device manufacturer
def manufacturer : String
File.read(@current_device_path / "manufacturer").rstrip
end
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved
end
47 changes: 47 additions & 0 deletions src/power_supply/battery.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require "../power_supply"

# Battery related informations
#
# ```
# # Run the command below to manually find the device available
# # `ls /sys/class/power_supply/`
# battery = Hardware::Battery.new("BAT0") # Specify the batery device name by yourself
# battery = Hardware::Battery.new_single # Will be looking for one available battery device
# ```
class Hardware::Battery < Hardware::PowerSupply
enum Status
Unknown
Charging
Discharging
NotCharging
Full
end

def initialize(supply_name : String)
@current_device_path = Path.new("#{DEVICE_DIRECTORY}/#{supply_name}")

unless type == Type::Battery
raise "Not a battery"
end
end
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved

def self.new_single
battery_power_device = self.entries_with_type.find { |entry| entry.type == Type::Battery }
if battery_power_device
self.new(battery_power_device.name)
else
raise "No battery device found"
end
end
j8r marked this conversation as resolved.
Show resolved Hide resolved

# The current battery power charge percentage
def capacity : UInt8
File.read(@current_device_path / "capacity").to_u8
end

# The current battery status
def status : Status
content = File.read(@current_device_path / "status").rstrip
Status.parse?(content.delete(' ')).not_nil!
andraantariksa marked this conversation as resolved.
Show resolved Hide resolved
end
end