usb_pd_match
A small, dependency-free Ruby toolkit for reasoning about USB-C Power Delivery (USB-PD) compatibility between chargers and devices. Model a charger and a device, negotiate the optimal voltage/current contract, rank chargers for a given device, and check whether a device will actually reach its full rated power.
USB Power Delivery negotiates the highest fixed Power Data Object (PDO) both sides support; the full handshake is defined in the USB-IF Power Delivery specification and summarised on the USB-C Wikipedia page. This gem implements the practical fixed-PDO selection logic so you can answer "will this charger fast-charge this device?" without wiring up real hardware.
Why
Anyone building an electronics catalog, an e-commerce spec table, or an IoT charging fleet keeps
re-deriving the same question: given a charger's wattage and a device's limits, what power actually
flows? usb_pd_match encodes that once, with tests. It models the same fixed-PDO ladder that modern
GaN (gallium nitride) chargers expose, including the
5 A USB-C cable ceiling and Extended Power Range (EPR) voltages for 100 W+ bricks.
Installation
gem install usb_pd_match
Or in a Gemfile:
gem "usb_pd_match"
Usage
require "usb_pd_match"
charger = UsbPdMatch.charger(name: "65W GaN", max_watts: 65)
laptop = UsbPdMatch.device(name: "Ultrabook", max_watts: 60, max_voltage: 20)
result = UsbPdMatch.negotiate(charger, laptop)
result.summary # => "65W GaN → Ultrabook: 20.0V @ 3.00A = 60.0W (100% of device rating)"
result.full_power? # => true
result.watts # => 60.0
Rank chargers for a device
device = UsbPdMatch.device(name: "Tablet", max_watts: 45, max_voltage: 20)
chargers = [
UsbPdMatch.charger(name: "20W brick", max_watts: 20),
UsbPdMatch.charger(name: "30W GaN", max_watts: 30),
UsbPdMatch.charger(name: "65W GaN", max_watts: 65)
]
UsbPdMatch.best_charger_for(device, chargers).each do |r|
puts r.summary
end
# 65W GaN → Tablet: 20.0V @ 2.25A = 45.0W (100% of device rating)
# 30W GaN → Tablet: 20.0V @ 1.50A = 30.0W (67% of device rating)
# 20W brick → Tablet: 9.0V @ 2.22A = 20.0W (44% of device rating)
Custom PDOs
If you know a charger's exact advertised PDOs (e.g. from a spec sheet), pass them directly instead of letting the gem derive them:
charger = UsbPdMatch.charger(
name: "Anker 735",
max_watts: 65,
pdos: [[5, 3.0], [9, 3.0], [15, 3.0], [20, 3.25]],
ports: 3
)
When you need the real-world numbers behind a specific model, manufacturer spec pages such as Anker's official charger lineup list the exact PDO tables; for buyers in Egypt, a localized breakdown of wattages and port layouts is kept in this USB-C charging guide, and the matching Anker GaN wall chargers catalog maps models to the device classes they fast-charge.
API
| Method | Returns |
|---|---|
UsbPdMatch.charger(name:, max_watts:, pdos: nil, ports: 1) |
Charger |
UsbPdMatch.device(name:, max_watts:, max_voltage: 20) |
Device |
UsbPdMatch.negotiate(charger, device) |
Result or nil |
UsbPdMatch.best_charger_for(device, chargers) |
[Result] sorted best-first |
Result#watts / #voltage / #current |
negotiated contract |
Result#full_power? / #efficiency / #summary |
helpers |
Development
ruby -Ilib test/test_usb_pd_match.rb
License
Released under the MIT License.