Skip to content

Commit

Permalink
Merge pull request #9 from xilopaint/feat/auto-update-feature
Browse files Browse the repository at this point in the history
Add auto-update feature, refactor code and fix bugs
  • Loading branch information
BenziAhamed authored Mar 16, 2019
2 parents 4e58614 + 3a95b8b commit 8133a93
Show file tree
Hide file tree
Showing 19 changed files with 383 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

.DS_Store
Binary file modified Battery.alfredworkflow
Binary file not shown.
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,4 @@

![Logo](info.png)

An Alfred app workflow to display battery information of your Apple laptop battery.

Keyword is `battery`.

[Download](https://github.com/BenziAhamed/alfred-battery/raw/master/Battery.alfredworkflow)
An Alfred workflow to display battery information of your Apple laptop.
Binary file modified info.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
116 changes: 116 additions & 0 deletions src/battery.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/env bash

INFO=$(ioreg -l -n AppleSmartBattery -r)

# Charge and time remaining
CURRENT_CAPACITY=$(echo "$INFO" | grep CurrentCapacity | awk '{printf $3; exit}')
MAX_CAPACITY=$(echo "$INFO" | grep MaxCapacity | awk '{printf $3; exit}')
CHARGE=$((CURRENT_CAPACITY * 100 / MAX_CAPACITY))
CELLS=$(python -c "f='●'*($CHARGE/10) + '○'*(10-$CHARGE/10); print f")
STATUS_INFO=Draining...

CHARGING=$(echo "$INFO" | grep -i ischarging | awk '{printf("%s", $3)}')
TIME_TO_EMPTY=$(echo "$INFO" | grep -i AvgTimeToEmpty | awk '{printf("%s", $3)}')
TIME_LEFT=Calculating…

if [ "$TIME_TO_EMPTY" -lt 15000 ]; then
TIME_LEFT=$(echo "$INFO" | grep -i AvgTimeToEmpty | awk '{printf("%i:%.2i", $3/60, $3%60)}')
fi

if [ "$CHARGING" == Yes ]; then
TIME_FULL=$(echo "$INFO" | grep -i AvgTimeToFull | tr '\n' ' | ' | awk '{printf("%i:%.2i", $3/60, $3%60)}')
TIME_INFO=$(echo "$TIME_FULL" until full)
STATUS_INFO=Charging...
BATT_ICON=charging.png
else
FULLY_CHARGED=$(echo "$INFO" | grep -i FullyCharged | awk '{printf("%s", $3)}')
EXTERNAL=$(echo "$INFO" | grep -i ExternalConnected | awk '{printf("%s", $3)}')
if [ "$FULLY_CHARGED" == Yes ]; then
if [ "$EXTERNAL" == Yes ]; then
TIME_INFO="On AC power"
STATUS_INFO="Fully Charged"
BATT_ICON=power.png
CHARGE="100"
CELLS="●●●●●●●●●●"
else
TIME_INFO=$TIME_LEFT
BATT_ICON=full.png
fi
else
TIME_INFO=$TIME_LEFT
BATT_ICON=critical.png
if [ "$CHARGE" -gt 80 ]; then
BATT_ICON=full.png
elif [ "$CHARGE" -gt 50 ]; then
BATT_ICON=medium.png
elif [ "$CHARGE" -gt 10 ]; then
BATT_ICON=low.png
fi
fi
fi
# Temperature
TEMPERATURE=$(echo "$INFO" | grep Temperature | awk '{printf ("%.1f", $3/10-273)}')
# Cycle count
CYCLE_COUNT=$(echo "$INFO" | grep -e '"CycleCount" =' | awk '{printf ("%i", $3)}')
# Battery health
DESIGN_CAPACITY=$(echo "$INFO" | grep DesignCapacity | awk '{printf $3; exit}')
HEALTH=$((MAX_CAPACITY * 100 / DESIGN_CAPACITY))
if [ "$HEALTH" -gt 100 ]; then
HEALTH=100
fi
# Serial
SERIAL=$(echo "$INFO" | grep BatterySerialNumber | awk '{printf ("%s", $3)}' | tr -d '"')
# Battery age
MANUFACTURE_DATE=$(echo "$INFO" | grep ManufactureDate | awk '{printf ("%i", $3)}')
day=$((MANUFACTURE_DATE&31))
month=$(((MANUFACTURE_DATE>>5)&15))
year=$((1980+(MANUFACTURE_DATE>>9)))
AGE=$(python -c "from datetime import date as D; d1=D.today(); d2=D($year, $month, $day); print ( (d1.year - d2.year)*12 + d1.month - d2.month )")
# Alfred feedback
cat << EOB
<?xml version="1.0"?>
<items>
<item>
<title>$CHARGE% $CELLS</title>
<subtitle>$STATUS_INFO</subtitle>
<icon>icons/$BATT_ICON</icon>
</item>
<item>
<title>$TIME_INFO</title>
<subtitle>Time Left</subtitle>
<icon>icons/clock.png</icon>
</item>
<item>
<title>$TEMPERATURE °C</title>
<subtitle>Temperature</subtitle>
<icon>icons/temp.png</icon>
</item>
<item>
<title>$CYCLE_COUNT</title>
<subtitle>Charge Cycles Completed</subtitle>
<icon>icons/cycles.png</icon>
</item>
<item>
<title>$HEALTH%</title>
<subtitle>Health</subtitle>
<icon>icons/health.png</icon>
</item>
<item>
<title>$SERIAL</title>
<subtitle>Serial</subtitle>
<icon>icons/serial.png</icon>
</item>
<item>
<title>$AGE months</title>
<subtitle>Age</subtitle>
<icon>icons/age.png</icon>
</item>
</items>
EOB
Binary file added src/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/age.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/charging.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/clock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/critical.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/cycles.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/full.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/health.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/low.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/medium.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/power.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/serial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/icons/temp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
264 changes: 264 additions & 0 deletions src/info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
<?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>bundleid</key>
<string>com.benzi.a2w.battery</string>
<key>category</key>
<string>Tools</string>
<key>connections</key>
<dict>
<key>3917FDAB-460E-4C28-A4A9-645B9773F34A</key>
<array>
<dict>
<key>destinationuid</key>
<string>FC5EB146-FA11-4E33-8456-F60EA94E7EEE</string>
<key>modifiers</key>
<integer>0</integer>
<key>modifiersubtext</key>
<string></string>
<key>vitoclose</key>
<false/>
</dict>
</array>
<key>FC5EB146-FA11-4E33-8456-F60EA94E7EEE</key>
<array/>
</dict>
<key>createdby</key>
<string>Benzi Ahamed</string>
<key>description</key>
<string>Displays information about your laptop battery</string>
<key>disabled</key>
<false/>
<key>name</key>
<string>Battery</string>
<key>objects</key>
<array>
<dict>
<key>config</key>
<dict>
<key>action</key>
<integer>0</integer>
<key>argument</key>
<integer>0</integer>
<key>focusedappvariable</key>
<false/>
<key>focusedappvariablename</key>
<string></string>
<key>hotkey</key>
<integer>0</integer>
<key>hotmod</key>
<integer>0</integer>
<key>leftcursor</key>
<false/>
<key>modsmode</key>
<integer>0</integer>
<key>relatedAppsMode</key>
<integer>0</integer>
</dict>
<key>type</key>
<string>alfred.workflow.trigger.hotkey</string>
<key>uid</key>
<string>3917FDAB-460E-4C28-A4A9-645B9773F34A</string>
<key>version</key>
<integer>2</integer>
</dict>
<dict>
<key>config</key>
<dict>
<key>alfredfiltersresults</key>
<false/>
<key>alfredfiltersresultsmatchmode</key>
<integer>0</integer>
<key>argumenttrimmode</key>
<integer>0</integer>
<key>argumenttype</key>
<integer>1</integer>
<key>escaping</key>
<integer>63</integer>
<key>keyword</key>
<string>battery</string>
<key>queuedelaycustom</key>
<integer>3</integer>
<key>queuedelayimmediatelyinitially</key>
<false/>
<key>queuedelaymode</key>
<integer>0</integer>
<key>queuemode</key>
<integer>1</integer>
<key>runningsubtext</key>
<string>Displays information about your battery, retrieving...</string>
<key>script</key>
<string>sh ./battery.sh</string>
<key>scriptargtype</key>
<integer>0</integer>
<key>scriptfile</key>
<string></string>
<key>subtext</key>
<string>Displays information about your battery</string>
<key>title</key>
<string>Battery</string>
<key>type</key>
<integer>0</integer>
<key>withspace</key>
<true/>
</dict>
<key>type</key>
<string>alfred.workflow.input.scriptfilter</string>
<key>uid</key>
<string>FC5EB146-FA11-4E33-8456-F60EA94E7EEE</string>
<key>version</key>
<integer>2</integer>
</dict>
<dict>
<key>config</key>
<dict>
<key>alfredfiltersresults</key>
<false/>
<key>alfredfiltersresultsmatchmode</key>
<integer>0</integer>
<key>argumenttrimmode</key>
<integer>0</integer>
<key>argumenttype</key>
<integer>2</integer>
<key>escaping</key>
<integer>102</integer>
<key>keyword</key>
<string>battery</string>
<key>queuedelaycustom</key>
<integer>3</integer>
<key>queuedelayimmediatelyinitially</key>
<true/>
<key>queuedelaymode</key>
<integer>0</integer>
<key>queuemode</key>
<integer>1</integer>
<key>runningsubtext</key>
<string></string>
<key>script</key>
<string># THESE VARIABLES MUST BE SET. SEE THE ONEUPDATER README FOR AN EXPLANATION OF EACH.
readonly remote_info_plist='https://raw.githubusercontent.com/BenziAhamed/alfred-battery/master/src/info.plist'
readonly workflow_url='BenziAhamed/alfred-battery'
readonly download_type='github_release'
readonly frequency_check='4'
# FROM HERE ON, CODE SHOULD BE LEFT UNTOUCHED!
function abort {
echo "${1}" &gt;&amp;2
exit 1
}
function url_exists {
curl --silent --location --output /dev/null --fail --range 0-0 "${1}"
}
function notification {
readonly local notificator="$(find . -type d -name 'Notificator.app')"
if [[ -n "${notificator}" ]]; then
"${notificator}/Contents/Resources/Scripts/notificator" --message "${1}" --title "${alfred_workflow_name}" --subtitle 'A new version is available'
return
fi
readonly local terminal_notifier="$(find . -type f -name 'terminal-notifier')"
if [[ -n "${terminal_notifier}" ]]; then
"${terminal_notifier}" -title "${alfred_workflow_name}" -subtitle 'A new version is available' -message "${1}"
return
fi
osascript -e "display notification \"${1}\" with title \"${alfred_workflow_name}\" subtitle \"A new version is available\""
}
# Local sanity checks
readonly local_info_plist='info.plist'
readonly local_version="$(/usr/libexec/PlistBuddy -c 'print version' "${local_info_plist}")"
[[ -n "${local_version}" ]] || abort 'You need to set a workflow version in the configuration sheet.'
[[ "${download_type}" =~ ^(direct|page|github_release)$ ]] || abort "'download_type' (${download_type}) needs to be one of 'direct', 'page', or 'github_release'."
[[ "${frequency_check}" =~ ^[0-9]+$ ]] || abort "'frequency_check' (${frequency_check}) needs to be a number."
# Check for updates
if [[ $(find "${local_info_plist}" -mtime +"${frequency_check}"d) ]]; then
if ! url_exists "${remote_info_plist}"; then abort "'remote_info_plist' (${remote_info_plist}) appears to not be reachable."; fi # Remote sanity check
readonly tmp_file="$(mktemp)"
curl --silent --location --output "${tmp_file}" "${remote_info_plist}"
readonly remote_version="$(/usr/libexec/PlistBuddy -c 'print version' "${tmp_file}")"
if [[ "${local_version}" == "${remote_version}" ]]; then
touch "${local_info_plist}" # Reset timer by touching local file
exit 0
fi
if [[ "${download_type}" == 'page' ]]; then
notification 'Opening download page…'
open "${workflow_url}"
exit 0
fi
download_url="$([[ "${download_type}" == 'github_release' ]] &amp;&amp; curl --silent "https://api.github.com/repos/${workflow_url}/releases/latest" | grep 'browser_download_url' | head -1 | sed -E 's/.*browser_download_url": "(.*)"/\1/' || echo "${workflow_url}")"
if url_exists "${download_url}"; then
notification 'Downloading and installing…'
curl --silent --location --output "${HOME}/Downloads/${alfred_workflow_name}.alfredworkflow" "${download_url}"
open "${HOME}/Downloads/${alfred_workflow_name}.alfredworkflow"
else
abort "'workflow_url' (${download_url}) appears to not be reachable."
fi
fi</string>
<key>scriptargtype</key>
<integer>1</integer>
<key>scriptfile</key>
<string></string>
<key>subtext</key>
<string></string>
<key>title</key>
<string></string>
<key>type</key>
<integer>0</integer>
<key>withspace</key>
<false/>
</dict>
<key>type</key>
<string>alfred.workflow.input.scriptfilter</string>
<key>uid</key>
<string>A35F4AB0-47ED-4FBB-8247-9EE1BCCAFFAD</string>
<key>version</key>
<integer>2</integer>
</dict>
</array>
<key>readme</key>
<string></string>
<key>uidata</key>
<dict>
<key>3917FDAB-460E-4C28-A4A9-645B9773F34A</key>
<dict>
<key>xpos</key>
<integer>30</integer>
<key>ypos</key>
<integer>30</integer>
</dict>
<key>A35F4AB0-47ED-4FBB-8247-9EE1BCCAFFAD</key>
<dict>
<key>colorindex</key>
<integer>12</integer>
<key>note</key>
<string>OneUpdater</string>
<key>xpos</key>
<integer>220</integer>
<key>ypos</key>
<integer>170</integer>
</dict>
<key>FC5EB146-FA11-4E33-8456-F60EA94E7EEE</key>
<dict>
<key>xpos</key>
<integer>220</integer>
<key>ypos</key>
<integer>30</integer>
</dict>
</dict>
<key>version</key>
<string>1.0</string>
<key>webaddress</key>
<string>benzi-ahamed.tumblr.com</string>
</dict>
</plist>

0 comments on commit 8133a93

Please sign in to comment.