From 5ce01658073cd740371d58ada428929a6d9cfada Mon Sep 17 00:00:00 2001 From: Matthew Petroff Date: Mon, 4 Feb 2013 14:20:24 -0500 Subject: [PATCH] Initial commit --- COPYING | 18 ++++++ README | 2 + kindle/display-weather.sh | 13 +++++ kindle/init-weather.sh | 5 ++ kindle/weather-image-error.png | Bin 0 -> 9921 bytes server/weather-script-preprocess.svg | 81 +++++++++++++++++++++++++++ server/weather-script.py | 66 ++++++++++++++++++++++ server/weather-script.sh | 8 +++ 8 files changed, 193 insertions(+) create mode 100755 COPYING create mode 100755 README create mode 100755 kindle/display-weather.sh create mode 100755 kindle/init-weather.sh create mode 100755 kindle/weather-image-error.png create mode 100755 server/weather-script-preprocess.svg create mode 100755 server/weather-script.py create mode 100755 server/weather-script.sh diff --git a/COPYING b/COPYING new file mode 100755 index 0000000..3ab62e6 --- /dev/null +++ b/COPYING @@ -0,0 +1,18 @@ +Copyright (c) 2012 Matthew Petroff + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README b/README new file mode 100755 index 0000000..71ccb31 --- /dev/null +++ b/README @@ -0,0 +1,2 @@ +From: +http://www.mpetroff.net/archives/2012/09/14/kindle-weather-display/ diff --git a/kindle/display-weather.sh b/kindle/display-weather.sh new file mode 100755 index 0000000..cfe841e --- /dev/null +++ b/kindle/display-weather.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +cd "$(dirname "$0")" + +rm weather-script-output.png +eips -c +eips -c + +if wget http://server/path/to/weather-script-output.png; then + eips -g weather-script-output.png +else + eips -g weather-image-error.png +fi diff --git a/kindle/init-weather.sh b/kindle/init-weather.sh new file mode 100755 index 0000000..13fe8fb --- /dev/null +++ b/kindle/init-weather.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +/etc/init.d/framework stop +/etc/init.d/powerd stop +/mnt/us/weather/display-weather.sh diff --git a/kindle/weather-image-error.png b/kindle/weather-image-error.png new file mode 100755 index 0000000000000000000000000000000000000000..cd5527d18bb5337c87cbd25f9948e4300cb6cdde GIT binary patch literal 9921 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 literal 0 HcmV?d00001 diff --git a/server/weather-script-preprocess.svg b/server/weather-script-preprocess.svg new file mode 100755 index 0000000..a05caf4 --- /dev/null +++ b/server/weather-script-preprocess.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Today: +High: +HIGH_ONE +°F +Low: +LOW_ONE +°F + +Tomorrow: +High: +HIGH_TWO +°F +Low: +LOW_TWO +°F + +DAY_THREE: +High: +HIGH_THREE +°F +Low: +LOW_THREE +°F + +DAY_FOUR: +High: +HIGH_FOUR +°F +Low: +LOW_FOUR +°F + + + + + + diff --git a/server/weather-script.py b/server/weather-script.py new file mode 100755 index 0000000..c89f807 --- /dev/null +++ b/server/weather-script.py @@ -0,0 +1,66 @@ +#!/usr/bin/python2 + +# Kindle Weather Display +# Matthew Petroff (http://www.mpetroff.net/) +# September 2012 + +import urllib2 +from xml.dom import minidom +import datetime +import codecs + + + +# +# Download and parse weather data +# + +# Fetch data (change lat and lon to desired location) +weather_xml = urllib2.urlopen('http://graphical.weather.gov/xml/SOAP_server/ndfdSOAPclientByDay.php?whichClient=NDFDgenByDay&lat=39.3286&lon=-76.6169&format=24+hourly&numDays=4&Unit=e').read() +dom = minidom.parseString(weather_xml) + +# Parse temperatures +xml_temperatures = dom.getElementsByTagName('temperature') +highs = [None]*4 +lows = [None]*4 +for item in xml_temperatures: + if item.getAttribute('type') == 'maximum': + values = item.getElementsByTagName('value') + for i in range(len(values)): + highs[i] = int(values[i].firstChild.nodeValue) + if item.getAttribute('type') == 'minimum': + values = item.getElementsByTagName('value') + for i in range(len(values)): + lows[i] = int(values[i].firstChild.nodeValue) + +# Parse icons +xml_icons = dom.getElementsByTagName('icon-link') +icons = [None]*4 +for i in range(len(xml_icons)): + icons[i] = xml_icons[i].firstChild.nodeValue.split('/')[-1].split('.')[0].rstrip('0123456789') + +# Parse dates +xml_day_one = dom.getElementsByTagName('start-valid-time')[0].firstChild.nodeValue[0:10] +day_one = datetime.datetime.strptime(xml_day_one, '%Y-%m-%d') + + + +# +# Preprocess SVG +# + +# Open SVG to process +output = codecs.open('weather-script-preprocess.svg', 'r', encoding='utf-8').read() + +# Insert icons and temperatures +output = output.replace('ICON_ONE',icons[0]).replace('ICON_TWO',icons[1]).replace('ICON_THREE',icons[2]).replace('ICON_FOUR',icons[3]) +output = output.replace('HIGH_ONE',str(highs[0])).replace('HIGH_TWO',str(highs[1])).replace('HIGH_THREE',str(highs[2])).replace('HIGH_FOUR',str(highs[3])) +output = output.replace('LOW_ONE',str(lows[0])).replace('LOW_TWO',str(lows[1])).replace('LOW_THREE',str(lows[2])).replace('LOW_FOUR',str(lows[3])) + +# Insert days of week +one_day = datetime.timedelta(days=1) +days_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] +output = output.replace('DAY_THREE',days_of_week[(day_one + 2*one_day).weekday()]).replace('DAY_FOUR',days_of_week[(day_one + 3*one_day).weekday()]) + +# Write output +codecs.open('weather-script-output.svg', 'w', encoding='utf-8').write(output) diff --git a/server/weather-script.sh b/server/weather-script.sh new file mode 100755 index 0000000..5549aac --- /dev/null +++ b/server/weather-script.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +cd "$(dirname "$0")" + +python2 weather-script.py +rsvg-convert --background-color=white -o weather-script-output.png weather-script-output.svg +pngcrush -c 0 -ow weather-script-output.png +cp -f weather-script-output.png /path/to/web/server/directory/weather-script-output.png