Adding the Weather to the tmux status bar


I decided to add a weather feature in my tmux status bar. I saw this could be done via powerline, and I initially tried to add it through there. I gave up after a few hours of trying to patch my fonts, although I must say powerline looks nice done right.

I then set out to work on rolling my own script to display the weather. It consisted of 3 parts: * A python script that fetched weather from the internet. * A launchd job to run it periodically. * A tmux command to read the file.

The python script was relatively simple. I got some api keys for the relevant services, and then found what data I wanted from my requests, and wrote it. I picked my default location as umass, in case geoIP lookup fails.

weather.py

#!/usr/bin/python2.7
import urllib3
import re
import us
import string
import json

http = urllib3.PoolManager()
req = http.request('get', "http://icanhazip.com")
ip = req.data[:-1]
#Defalit location
state = "MA"
town = "Amherst"
#where are we?
req = http.request('GET', 'http://api.ipinfodb.com/v3/ip-city/?key=APIKEY&ip=' + ip)
if req.status == 200:
    data = re.split(';', req.data)
    state = (us.states.lookup(data[5]).abbr).upper()
    town = data[6].replace(' ', '_')
#get weather conditions
weatherAddress = string.Template("http://api.wunderground.com/api/APIKEY/conditions/q/$@state/$@town.json").substitute({'state':state,'town':town})
req = http.request('GET', weatherAddress)
conditions =  json.loads('[' + req.data + ']')[0]
forecastAddress = string.Template("http://api.wunderground.com/api/APIKEY/forecast/q/$@state/$@town.json").substitute({'state':state,'town':town})
req = http.request('GET', forecastAddress)
forecast =  json.loads('[' + req.data + ']')[0]
#output weather to file
output = "$@weather, $@future $@{temperature}, $@hi/$@low F, $@wind mph"
weatherdic ={'weather': conditions['current_observation']['weather'], 'future':forecast['forecast']['simpleforecast']['forecastday'][1]['conditions'], 'temperature':conditions['current_observation']['temperature_string'], 'hi': forecast['forecast']['simpleforecast']['forecastday'][0]['high']['fahrenheit'], \
    'low':forecast['forecast']['simpleforecast']['forecastday'][0]['low']['fahrenheit'], 'wind': forecast['forecast']['simpleforecast']['forecastday'][0]['avewind']['mph']}
with open('/Users/ahalbert/.weather', 'w') as weatherfile:
    weatherfile.write(string.Template(output).substitute(weatherdic))

I then tried to set up a cron job. This, however ended in failure when I realized launchctl had replaced cron. So after reading through the launchctl documentation, I added the following to ~/Library/LaunchAgents/

org.ahalbert.weather.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>org.ahalbert.weather</string>
<key>ProgramArguments</key>
    <array>
    <string>/Users/ahalbert/dotfiles/weather.py</string>
    </array>
<key>StartInterval</key>
<integer>1800</integer>
</dict>
</plist>

Of course, even after this, launchctl load ~/Library/LaunchAgents/org.ahalbert.weather.plist gave me a permission denied error, which is due to running the command in iterm and/or tmux, when it must be done in Terminal.app.

I also had to be reminded that /bin/sh does not execute as me, and requires extra permissions to read/execute my file. However, now information is gathered every 30 minutes, and put into my .weather file.

The last part involved setting up my tmux configuration. I added:

set status-interval 30 #update every 30 seconds
set -g status-right-length 150 #Weather string is longer than the default so I had to extend it
set -g status-right '#(cat ~/.weather) #h #(~/dotfiles/battery.sh) %y-%m-%d %H:%M'

Battery!

You may have noticed battery.sh in my configuration, I also wrote a battery script, which consists of

!#/bin/bash
ioreg -l | grep -i capacity | tr '\n' ' | ' | awk '{printf("%.2f%%", $@10/$@5 * 100)}' |  grep -v '^$@'

The results:

weather

I am quite happy with it. I no longer need to switch to the dashboard if I want to see a weather forecast.


<< Previous Next >>