I wanted to track battery data over time and have not found a reasonable approach using the current apps to store the information in a database. I decided the first step was to figure out how to pull the information and store in a CSV file. Next steps include either pushing to PostgresSQL and to Google Sheets.
First I found the ioreg command which enabled me to pull the data. I could have used a shell script but preferred to use Python 3 since it would give me more options in the future.
I used the command
ioreg -rd1 -c AppleSmartBattery
Which enabled me to pull just the battery information I was interested in. I was able to use python to pull specific items and push to a csv file. I'm not sure I got everything I wanted but it is a start. Once the program worked I created a plist file to run it every 60 minutes via LaunchAgent. The cool part of LaunchAgents is the ability to run after coming out of sleep mode.
I did install pyinstaller to create an "executable" which I placed in the bin directory and it writes to a data directory. Below find the program and plist I used.
local.batteryinfo.plist
<?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">
<dict>
<key>Label</key>
<string>com.username.personal.batteryinfo</string>
<key>Program</key>
<string>/Users/username/bin/battery-info</string>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/dev/null</string>
<key>StandardOutPath</key>
<string>/Users/username/data/batteryinfo.out</string>
<key>StartInterval</key>
<integer>3600</integer>
<key>WorkingDirectory</key>
<string>/Users/username/data</string>
</dict>
</plist>
!/opt/homebrew/bin/python3import subprocessfrom csv import DictWriterfrom datetime import datetime# datetime object containing current date and timenow = datetime.now()nowDate = now.strftime("%Y%m%d")nowTime = now.strftime("%H%M%S")fileName = "/Users/username/data/batteryinfo.csv"batteryRawInfo = {}batteryInfo = {}excludeList = ['+-o', '{', '}', "\r"]headersCSV = ['Date','Time','DeviceName','AtCriticalLevel','ExternalConnected','AppleRawCurrentCapacity','Serial','NominalChargeCapacity','FullyCharged','DesignCycleCount9C','MaxCapacity','DesignCapacity','IsCharging','CycleCount','AppleRawMaxCapacity','TimeRemaining','Temperature','VirtualTemperature','AtCriticalLevel',]def exist_and_not_empty(filepath):try:import pathlib as ppath = p.Path(filepath)if '~' in filepath:path = path.expanduser()if not path.exists() and path.stat().st_size > 0:return Falsereturn Trueexcept FileNotFoundError:return Falsedef writeCSVFile(fileName, headers, batDict):with open(fileName, 'a', newline='') as f_object:# Pass the CSV file object to the Dictwriter() function# Result - a DictWriter objectdictwriter_object = DictWriter(f_object, fieldnames=headers)# Pass the data in the dictionary as an argument into the writerow() functiondictwriter_object.writerow(batDict)# Close the file objectf_object.close()def main():with subprocess.Popen(['ioreg', '-rd1', '-c', 'AppleSmartBattery'], stdout=subprocess.PIPE, text=True) as proc:# print(proc.__dict__)# with proc.stdout.read() as stdoutString:,# print(stdoutString)batteryLines = proc.stdout.readlines()for line in batteryLines:if [ele for ele in excludeList if (ele in line)]:continue# print("Line: [{}]".format(line.strip().replace(' ','').replace('"','')))if "=" in line:(k, v) = line.strip().replace(' ', '').replace('"', '').split("=")batteryRawInfo[k] = v# print("Dictionary ........................... ")# print(batteryRawInfo)for key, value in batteryRawInfo.items():# print(f'Key: {key}, Value: {value}')if key in headersCSV:batteryInfo[key] = valuebatteryInfo["Date"] = nowDatebatteryInfo["Time"] = nowTime# print(batteryInfo)writeCSVFile(fileName, headersCSV, batteryInfo)if __name__ == '__main__':main()
I did have some issues loading the launch agent and finally download an application called LaunchControl. Helped with a permissions issue and fixed my issue.
Enjoy.