svartalf / rust-battery

Rust crate providing cross-platform information about the notebook batteries.
https://crates.io/crates/battery
Apache License 2.0
358 stars 40 forks source link

Fix overflow and change time to minutes on MacOS #11

Closed martinrlilja closed 5 years ago

martinrlilja commented 5 years ago

Amperage was returning negative values, so I changed it to read as an isize and then getting the absolute value from it.

percentage() was also overflowing. I changed it to use the capacity values directly instead of going through the energy functions. The multiplication with voltage should cancel out either way.

InstantTimeToEmpty is returning the time in minutes, at least on my system. I haven't gotten InstantTimeToFull to report anything yet, instead it's reporting both values through TimeRemaining. (I haven't looked into this, just mentioning it)

I have only tested this on Mojave (10.14.3)

svartalf commented 5 years ago

Could you also attach output from the ioreg -n AppleSmartBattery -r -a terminal command when the bug happens?

Same to #10, it would be nice to collect some real-life data and cover that case with test later.

svartalf commented 5 years ago

Also, InstantTimeToEmpty and InstantTimeToFull keys are not documented at the IOPMPowerSource, maybe that is a reason :)

There is also TimeRemaining key exists, maybe I should use it instead, collecting data from the ioreg would help to choose the right thing.

martinrlilja commented 5 years ago
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>AdapterInfo</key>
        <integer>0</integer>
        <key>Amperage</key>
        <integer>0</integer>
        <key>AppleRawCurrentCapacity</key>
        <integer>3637</integer>
        <key>AppleRawMaxCapacity</key>
        <integer>3688</integer>
        <key>AvgTimeToEmpty</key>
        <integer>65535</integer>
        <key>AvgTimeToFull</key>
        <integer>65535</integer>
        <key>BatteryData</key>
        <dict>
            <key>CycleCount</key>
            <integer>266</integer>
            <key>DesignCapacity</key>
            <integer>4315</integer>
            <key>QmaxCell0</key>
            <integer>43791</integer>
            <key>QmaxCell1</key>
            <integer>49935</integer>
            <key>QmaxCell2</key>
            <integer>12560</integer>
            <key>ResScale</key>
            <integer>32000</integer>
            <key>StateOfCharge</key>
            <integer>25344</integer>
            <key>Voltage</key>
            <integer>12804</integer>
        </dict>
        <key>BatteryFCCData</key>
        <dict>
            <key>DOD0</key>
            <integer>0</integer>
            <key>DOD1</key>
            <integer>0</integer>
            <key>DOD2</key>
            <integer>0</integer>
            <key>PassedCharge</key>
            <integer>0</integer>
            <key>ResScale</key>
            <integer>32000</integer>
        </dict>
        <key>BatteryInstalled</key>
        <true/>
        <key>BatteryInvalidWakeSeconds</key>
        <integer>30</integer>
        <key>BatterySerialNumber</key>
        <string>#####</string>
        <key>BootPathUpdated</key>
        <integer>#####</integer>
        <key>CellVoltage</key>
        <array>
            <integer>4272</integer>
            <integer>4271</integer>
            <integer>4261</integer>
            <integer>0</integer>
        </array>
        <key>ChargerData</key>
        <dict>
            <key>ChargingCurrent</key>
            <integer>0</integer>
            <key>ChargingVoltage</key>
            <integer>64050</integer>
            <key>NotChargingReason</key>
            <integer>4</integer>
        </dict>
        <key>CurrentCapacity</key>
        <integer>3637</integer>
        <key>CycleCount</key>
        <integer>266</integer>
        <key>DesignCapacity</key>
        <integer>4315</integer>
        <key>DesignCycleCount70</key>
        <integer>0</integer>
        <key>DesignCycleCount9C</key>
        <integer>1000</integer>
        <key>DeviceName</key>
        <string>bq20z451</string>
        <key>ExternalChargeCapable</key>
        <true/>
        <key>ExternalConnected</key>
        <true/>
        <key>FirmwareSerialNumber</key>
        <integer>1</integer>
        <key>FullPathUpdated</key>
        <integer>######</integer>
        <key>FullyCharged</key>
        <true/>
        <key>IOGeneralInterest</key>
        <string>IOCommand is not serializable</string>
        <key>IOObjectClass</key>
        <string>AppleSmartBattery</string>
        <key>IOObjectRetainCount</key>
        <integer>6</integer>
        <key>IORegistryEntryID</key>
        <integer>4294967992</integer>
        <key>IORegistryEntryName</key>
        <string>AppleSmartBattery</string>
        <key>IOReportLegend</key>
        <array>
            <dict>
                <key>IOReportChannelInfo</key>
                <dict>
                    <key>IOReportChannelUnit</key>
                    <integer>0</integer>
                </dict>
                <key>IOReportChannels</key>
                <array>
                    <array>
                        <integer>7167869599145487988</integer>
                        <integer>6460407809</integer>
                        <string>BatteryCycleCount</string>
                    </array>
                </array>
                <key>IOReportGroupName</key>
                <string>Battery</string>
            </dict>
        </array>
        <key>IOReportLegendPublic</key>
        <true/>
        <key>IOServiceBusyState</key>
        <integer>0</integer>
        <key>IOServiceBusyTime</key>
        <integer>35339</integer>
        <key>IOServiceState</key>
        <integer>30</integer>
        <key>InstantAmperage</key>
        <integer>0</integer>
        <key>InstantTimeToEmpty</key>
        <integer>1307</integer>
        <key>IsCharging</key>
        <false/>
        <key>LegacyBatteryInfo</key>
        <dict>
            <key>Amperage</key>
            <integer>0</integer>
            <key>Capacity</key>
            <integer>3688</integer>
            <key>Current</key>
            <integer>3637</integer>
            <key>Cycle Count</key>
            <integer>266</integer>
            <key>Flags</key>
            <integer>5</integer>
            <key>Voltage</key>
            <integer>12804</integer>
        </dict>
        <key>Location</key>
        <integer>0</integer>
        <key>ManufactureDate</key>
        <integer>19043</integer>
        <key>Manufacturer</key>
        <string>SMP</string>
        <key>ManufacturerData</key>
        <data>
        #####
        </data>
        <key>MaxCapacity</key>
        <integer>3688</integer>
        <key>MaxErr</key>
        <integer>1</integer>
        <key>OperationStatus</key>
        <integer>58435</integer>
        <key>PackReserve</key>
        <integer>125</integer>
        <key>PermanentFailureStatus</key>
        <integer>0</integer>
        <key>PostChargeWaitSeconds</key>
        <integer>120</integer>
        <key>PostDischargeWaitSeconds</key>
        <integer>120</integer>
        <key>Temperature</key>
        <integer>2993</integer>
        <key>TimeRemaining</key>
        <integer>0</integer>
        <key>UserVisiblePathUpdated</key>
        <integer>1551132291</integer>
        <key>Voltage</key>
        <integer>12804</integer>
    </dict>
</array>
</plist>
svartalf commented 5 years ago

Hey, @martinrlilja!

You were right, time values are definitely returned in minutes, not a seconds. Since your changes was partially fixed by #10 and I've also decided to switch from InstantTimeToEmpty and InstantTimeToFull to the documented TimeRemaining key, it seemed easier not to bother you with rebase requests and do it myself.

Therefore, I'm closing this PR, many thanks for your help :)

Edit: fixed versions are already published to the crates.io