This commit is contained in:
Tom Keffer
2011-03-29 19:32:11 +00:00
13 changed files with 504 additions and 229 deletions

View File

@@ -1,7 +1,10 @@
CHANGE HISTORY
--------------------------------
1.10.0a6 02/26/11
1.10.0 03/29/11
Added extensive almanac information if the optional package 'pyephem' has been
installed
Added a weewx "favorite icon" favicon.ico that displays in your browser toolbar.

View File

@@ -19,7 +19,6 @@ bin/user/schemas.py
bin/weeplot/__init__.py
bin/weeplot/genplot.py
bin/weeplot/utilities.py
bin/weeutil/Almanac.py
bin/weeutil/Moon.py
bin/weeutil/Sun.py
bin/weeutil/__init__.py
@@ -29,6 +28,7 @@ bin/weeutil/weeutil.py
bin/weewx/VantagePro.py
bin/weewx/__init__.py
bin/weewx/accum.py
bin/weewx/almanac.py
bin/weewx/archive.py
bin/weewx/crc16.py
bin/weewx/filegenerator.py

View File

@@ -12,7 +12,7 @@
"""
import time
__version__="1.10.0a6"
__version__="1.10.0"
# Holds the program launch time in unix epoch seconds:
# Useful for calculating 'uptime.'

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2009 Tom Keffer <tkeffer@gmail.com>
# Copyright (c) 2009, 2011 Tom Keffer <tkeffer@gmail.com>
#
# See the file LICENSE.txt for your full rights.
#
@@ -12,47 +12,23 @@
This module can optionally use PyEphem, which offers high quality
astronomical calculations. See http://rhodesmill.org/pyephem. """
#===============================================================================
# Architectural notes
#
# Unfortunately, sunrise and sunset have to be calculated dynamically when
# using ephem because of its unfortunate design decision to change the
# state of the body when calling next_rising() or next_setting(). This leads
# to some complications in the class BodyWrapper
#===============================================================================
import calendar
import time
import sys
import Moon
import weeutil.Moon
import weewx.units
# If the user has installed ephem, use it. Otherwise, fall back to the weeutil algorithms:
try:
import ephem
import math
except:
import Sun
import weeutil.Sun
class Almanac(object):
"""Almanac data.
time_ts: A timestamp within the date for which sunrise/sunset is desired.
lat, lon: Location for which sunrise/sunset is desired.
altitude: Elevation in **meters**. [Optional. Default is 0 (sea level)]
temperature: The temperature in **degrees Celsius**. [Optional. Default is 15.0]
pressure: The atmospheric pressure in **mBars**. [Optional. Default is 1010]
moon_phases: An array of 8 strings with descriptions of the moon
phase. [optional. If not given, then weeutil.Moon.moon_phases will be used]
timeformat: A strftime style format to be used to format sunrise and sunset.
[optional. If not given, then "%H:%M" will be used.
ATTRIBUTES.
As a minimum, the following attributes are available:
@@ -62,58 +38,60 @@ class Almanac(object):
moon_phase: A description of the moon phase(eg. "new moon", Waxing crescent", etc.)
moon_fullness: Percent fullness of the moon (0=new moon, 100=full moon)
If the module 'ephem' is used, many other attributes are available.
If the module 'ephem' is used, them many other attributes are available.
Here are a few examples:
sun.transit: Time of transit (sun over meridian)
sun.previous_sunrise: Time of last sunrise
sun.rise: Time upper limb of sun will rise above the horizon today in unix epoch time
sun.transit: Time of transit today (sun over meridian) in unix epoch time
sun.previous_sunrise: Time of last sunrise in unix epoch time
sun.az: Azimuth (in degrees) of sun
sun.alt: Altitude (in degrees) of sun
mars.rise: Time of mars rising
mars.rise: Time when upper limb of mars will rise above horizon today in unix epoch time
mars.ra: Right ascension of mars
etc.
EXAMPLES:
>>> t = time.mktime((2009, 3, 27, 12, 0, 0, 0, 0, -1))
>>> print weeutil.timestamp_to_string(t)
>>> print timestamp_to_string(t)
2009-03-27 12:00:00 PDT (1238180400)
>>> almanac = Almanac(t, 46.0, -122.0)
Test backwards compatiblity with attributes 'sunrise' and 'sunset'
>>> print "Sunrise, sunset:", almanac.sunrise, almanac.sunset
Sunrise, sunset: 06:56 19:30
Test backwards compatiblity with attribute 'moon_fullness':
Test backwards compatibility with attribute 'moon_fullness':
>>> print "Fullness of the moon (rounded) is %.2f%% [%s]" % (almanac.moon_fullness, almanac.moon_phase)
Fullness of the moon (rounded) is 2.00% [new (totally dark)]
Now get a more precise result for fullness of the moon:
>>> print "Fullness of the moon (more precise) is %.2f" % almanac.moon.moon_phase
Fullness of the moon (more precise) is 1.70
>>> print "Fullness of the moon (more precise) is %.2f%%" % almanac.moon.moon_phase
Fullness of the moon (more precise) is 1.70%
Test backwards compatibility with attributes 'sunrise' and 'sunset'
>>> print "Sunrise, sunset:", almanac.sunrise, almanac.sunset
Sunrise, sunset: 06:56 19:30
Get sunrise, sun transit, and sunset using the new 'ephem' syntax:
>>> print "Sunrise, sun transit, sunset:", almanac.sun.rise, almanac.sun.transit, almanac.sun.set
Sunrise, sun transit, sunset: 06:56 13:13 19:30
Do the same with the moon:
>>> print "Moon rise, moon transit, moon set:", almanac.moon.rise, almanac.moon.transit, almanac.moon.set
Moon rise, moon transit, moon set: 06:59 14:01 21:20
>>> print "Moon rise, transit, set:", almanac.moon.rise, almanac.moon.transit, almanac.moon.set
Moon rise, transit, set: 06:59 14:01 21:20
Exercise equinox, solstice routines
>>> print weeutil.timestamp_to_string(almanac.next_vernal_equinox)
2010-03-20 10:32:10 PDT (1269106330)
>>> print weeutil.timestamp_to_string(almanac.next_autumnal_equinox)
2009-09-22 14:18:38 PDT (1253654318)
>>> print weeutil.timestamp_to_string(almanac.next_summer_solstice)
2009-06-20 22:45:40 PDT (1245563140)
>>> print weeutil.timestamp_to_string(almanac.next_winter_solstice)
2009-12-21 09:46:38 PST (1261417598)
>>> print almanac.next_vernal_equinox
20-Mar-2010 10:32
>>> print almanac.next_autumnal_equinox
22-Sep-2009 14:18
>>> print almanac.next_summer_solstice
20-Jun-2009 22:45
>>> print almanac.next_winter_solstice
21-Dec-2009 09:46
Exercise moon state routines
>>> print weeutil.timestamp_to_string(almanac.next_full_moon)
2009-04-09 07:55:49 PDT (1239288949)
>>> print weeutil.timestamp_to_string(almanac.next_new_moon)
2009-04-24 20:22:33 PDT (1240629753)
>>> print almanac.next_full_moon
09-Apr-2009 07:55
>>> print almanac.next_new_moon
24-Apr-2009 20:22
Now location of the sun and moon
>>> print "Solar azimuth, altitude = (%.2f, %.2f)" % (almanac.sun.az, almanac.sun.alt)
@@ -122,21 +100,37 @@ class Almanac(object):
Moon azimuth, altitude = (133.55, 47.89)
"""
def __init__(self, time_ts, lat, lon,
altitude=0, temperature=15.0, pressure=1010.0,
moon_phases=Moon.moon_phases, timeformat="%H:%M"):
self.lat = lat
self.lon = lon
self.altitude = altitude
self.temperature = temperature
self.pressure = pressure
self.timeformat = timeformat
self.date_tt = (0, 0, 0, 0, 0, 0)
def __init__(self, time_ts, lat, lon,
altitude=0.0, temperature=15.0, pressure=1010.0,
moon_phases=weeutil.Moon.moon_phases,
formatter=weewx.units.Formatter()):
"""Initialize an instance of Almanac
self.moon_phases = moon_phases
self.moon_phase = ''
self.moon_fullness = None
time_ts: A unix epoch timestamp for which the almanac will be current.
lat, lon: Observer's location
altitude: Observer's elevation in **meters**. [Optional. Default is 0 (sea level)]
temperature: Observer's temperature in **degrees Celsius**. [Optional. Default is 15.0]
pressure: Observer's atmospheric pressure in **mBars**. [Optional. Default is 1010]
moon_phases: An array of 8 strings with descriptions of the moon
phase. [optional. If not given, then weeutil.Moon.moon_phases will be used]
formatter: An instance of weewx.units.Formatter() with the formatting information
to be used.
"""
self.lat = lat
self.lon = lon
self.altitude = altitude
self.temperature = temperature
self.pressure = pressure
self.moon_phases = moon_phases
self.formatter = formatter
self.date_tt = (0, 0, 0, 0, 0, 0)
self.hasExtras = False
self.setTime(time_ts)
@@ -150,76 +144,65 @@ class Almanac(object):
if _newdate_tt[0:6] != self.date_tt[0:6] :
(y,m,d) = _newdate_tt[0:3]
(moon_index, _moon_fullness) = Moon.moon_phase(y, m, d)
self.moon_phase = self.moon_phases[moon_index] if self.moon_phases is not None else ''
(self.moon_index, self._moon_fullness) = weeutil.Moon.moon_phase(y, m, d)
self.moon_phase = self.moon_phases[self.moon_index]
# Check to see whether the user has module 'ephem'. If so, use it.
if sys.modules.has_key('ephem'):
# Set up an observer object holding the location and time:
stn = ephem.Observer()
stn.long = math.radians(self.lon)
stn.lat = math.radians(self.lat)
stn.long = math.radians(self.lon)
stn.elev = self.altitude
stn.temp = self.temperature
stn.pressure = self.pressure
stn.date = self.time_j1899 = timestamp_to_j1899(time_ts)
stn.date = self.time_djd = timestamp_to_djd(time_ts)
# Sun calculations:
self.sun = BodyWrapper(ephem.Sun, stn, self.timeformat) #@UndefinedVariable
# Moon calculations:
self.moon = BodyWrapper(ephem.Moon, stn, self.timeformat)
# Venus calculations:
self.venus = BodyWrapper(ephem.Venus, stn, self.timeformat) #@UndefinedVariable
# Mars calculations:
self.mars = BodyWrapper(ephem.Mars, stn, self.timeformat) #@UndefinedVariable
# Jupiter calculations:
self.jupiter = BodyWrapper(ephem.Jupiter, stn, self.timeformat)
# This attribute is here for backwards compatiblity.
# For full precision, use attribute moon.moon_phase
self.moon_fullness = int(self.moon.moon_phase+0.5)
# The various celestial bodies offered by the almanac:
self.sun = BodyWrapper(ephem.Sun, stn, self.formatter) #@UndefinedVariable
self.moon = BodyWrapper(ephem.Moon, stn, self.formatter)
self.venus = BodyWrapper(ephem.Venus, stn, self.formatter) #@UndefinedVariable
self.mars = BodyWrapper(ephem.Mars, stn, self.formatter) #@UndefinedVariable
self.jupiter = BodyWrapper(ephem.Jupiter, stn, self.formatter)
self.hasExtras = True
else:
# No ephem package. Use the weeutil algorithms. Less accurate, but they get the
# job done.
(sunrise_utc, sunset_utc) = Sun.sunRiseSet(y, m, d, self.lon, self.lat)
# No ephem package. Use the weeutil algorithms, which supply a minimum of functionality
(sunrise_utc, sunset_utc) = weeutil.Sun.sunRiseSet(y, m, d, self.lon, self.lat)
# The above function returns its results in UTC hours. Convert
# to a local time tuple
sunrise_tt = Almanac._adjustTime(y, m, d, sunrise_utc)
sunset_tt = Almanac._adjustTime(y, m, d, sunset_utc)
self._sunrise = time.strftime(self.timeformat, sunrise_tt)
self._sunset = time.strftime(self.timeformat, sunset_tt)
self._sunrise = time.strftime("%H:%M", sunrise_tt)
self._sunset = time.strftime("%H:%M", sunset_tt)
self.moon_fullness = _moon_fullness
self.hasExtras = False
self.date_tt = _newdate_tt
# Short cuts, used for backwards compatibility
# Shortcuts, used for backwards compatibility
@property
def sunrise(self):
return self.sun.rise if self.hasExtras else self._sunrise
@property
def sunset(self):
return self.sun.set if self.hasExtras else self._sunset
@property
def moon_fullness(self):
return int(self.moon.moon_phase+0.5) if self.hasExtras else self._moon_fullness
def __getattr__(self, attr):
if self.hasExtras and attr in ['next_autumnal_equinox', 'next_vernal_equinox',
if self.hasExtras and attr in ['next_equinox', 'next_solstice',
'next_autumnal_equinox', 'next_vernal_equinox',
'next_winter_solstice', 'next_summer_solstice',
'next_full_moon', 'next_new_moon']:
# This is how you call a function on an instance when all you have is its name:
j1899 = ephem.__dict__[attr](self.time_j1899) #@UndefinedVariable
t = j1899_to_timestamp(j1899)
return t
djd = ephem.__dict__[attr](self.time_djd) #@UndefinedVariable
return weewx.units.ValueHelper((djd, "dublin_jd", "group_time"),
context="ephem_year", formatter=self.formatter)
else:
raise AttributeError, "Unknown attribute "+attr
@@ -246,10 +229,11 @@ fn_map = {'rise' : 'next_rising',
class BodyWrapper(object):
"""This class wraps a celestial body. It returns results in degrees (instead of radians)
and percent (instead of fractions). It also deals with the unfortunately side-effect
of changing the state of the body with certain functions."""
and percent (instead of fractions). For times, it returns the results as a ValueHelper.
It also deals with the unfortunate design decision in pyephem to change
the state of the celestial body when using it as an argument in certain functions."""
def __init__(self, body_factory, observer, timeformat="%H:%M"):
def __init__(self, body_factory, observer, formatter):
"""Initialize a wrapper
body_factory: A function that returns an instance of the body
@@ -257,62 +241,63 @@ class BodyWrapper(object):
observer: An instance of ephem.Observer, containing the observer's lat, lon, time, etc.
timeformat: A strftime style format to be used to format sunrise and sunset.
[optional. If not given, then "%H:%M" will be used.
formatter: An instance of weewx.units.Formatter(), containing the formatting
to be used for times.
"""
self.body_factory = body_factory
self.observer = observer
self.timeformat = timeformat
self.formatter = formatter
self.body = body_factory(observer)
(y,m,d) = time.localtime(j1899_to_timestamp(observer.date))[0:3]
self.sod_j1899 = timestamp_to_j1899(time.mktime((y,m,d,0,0,0,0,0,-1)))
# Calculate and store the start-of-day in Dublin Julian Days:
(y,m,d) = time.localtime(djd_to_timestamp(observer.date))[0:3]
self.sod_djd = timestamp_to_djd(time.mktime((y,m,d,0,0,0,0,0,-1)))
def __getattr__(self, attr):
if attr in ['az', 'alt', 'a_ra', 'a_dec', 'g_ra', 'ra', 'g_dec', 'dec',
'elong', 'radius', 'hlong', 'hlat', 'sublat', 'sublong']:
# Return the results in degrees rather than radians
v = getattr(self.body, attr)
return math.degrees(v)
return math.degrees(getattr(self.body, attr))
elif attr=='moon_phase':
# Return the result in percent
v = getattr(self.body, attr)
return 100.0 * v
return 100.0 * self.body.moon_phase
elif attr in ['next_rising', 'next_setting', 'next_transit', 'next_antitransit',
'previous_rising', 'previous_setting', 'previous_transit', 'previous_antitransit']:
# These functions have the unfortunate side effect of changing the state of the body
# being examined. So, create a temporary body and then throw it away
temp_body = self.body_factory()
time_j1899 = getattr(self.observer, attr)(temp_body)
return j1899_to_string(time_j1899, self.timeformat)
elif attr in ['rise', 'set', 'transit']:
# These functions have the unfortunate side effect of changing the state of the body
# being examined. So, create a temporary body and then throw it away
time_djd = getattr(self.observer, attr)(temp_body)
return weewx.units.ValueHelper((time_djd, "dublin_jd", "group_time"), context="ephem_day", formatter=self.formatter)
elif attr in fn_map:
# These attribute names have to be mapped to a different function name. Like the
# attributes above, they also have the side effect of changing the state of the body.
# Finally, they return the time of the event anywhere in the day (not just the next
# event), so they take a second argument in the function call.
temp_body = self.body_factory(self.observer)
# Look up the function to be called for this attribute (eg, call 'next_rising' for 'rise')
fn = fn_map[attr]
time_j1899 = getattr(self.observer, fn)(temp_body, self.sod_j1899)
return j1899_to_string(time_j1899, self.timeformat)
# Call the function, with a second argument giving the start-of-day
time_djd = getattr(self.observer, fn)(temp_body, self.sod_djd)
return weewx.units.ValueHelper((time_djd, "dublin_jd", "group_time"), context="ephem_day", formatter=self.formatter)
else:
# Just return the result unchanged.
return getattr(self.body, attr)
def timestamp_to_j1899(time_ts):
"""Convert from a unix time stamp to the number of days since 12/31/1899 12:00 UTC"""
def timestamp_to_djd(time_ts):
"""Convert from a unix time stamp to the number of days since 12/31/1899 12:00 UTC
(aka "Dublin Julian Days")"""
# The number 25567.5 is the start of the Unix epoch (1/1/1970). Just add on the
# number of days since then
return 25567.5 + time_ts/86400.0
def j1899_to_timestamp(j1899):
"""Convert from number of days since 12/31/1899 12:00 UTC to unix time stamp"""
return (j1899-25567.5) * 86400.0
def j1899_to_string(j1899, timeformat="%H:%M"):
time_tt = time.localtime(j1899_to_timestamp(j1899))
return time.strftime(timeformat, time_tt)
def djd_to_timestamp(djd):
"""Convert from number of days since 12/31/1899 12:00 UTC ("Dublin Julian Days") to unix time stamp"""
return (djd-25567.5) * 86400.0
if __name__ == '__main__':
import doctest
import weeutil #@UnusedImport
from weeutil.weeutil import timestamp_to_string #@UnusedImport
doctest.testmod()

View File

@@ -17,8 +17,8 @@ import time
import Cheetah.Template
import Cheetah.Filters
import weeutil.Almanac
import weeutil.weeutil
import weewx.almanac
import weewx.archive
import weewx.reportengine
import weewx.station
@@ -304,13 +304,14 @@ class FileGenerator(weewx.reportengine.ReportGenerator):
if temperature_C is None: temperature_C = 15.0
if pressure_mbar is None: pressure_mbar = 1010.0
self.almanac = weeutil.Almanac.Almanac(celestial_ts,
self.station.latitude_f,
self.station.longitude_f,
altitude_vt[0],
temperature_C,
pressure_mbar,
self.moonphases)
self.almanac = weewx.almanac.Almanac(celestial_ts,
self.station.latitude_f,
self.station.longitude_f,
altitude_vt[0],
temperature_C,
pressure_mbar,
self.moonphases,
self.formatter)
def _prepGen(self, subskin_dict):

View File

@@ -168,7 +168,9 @@ conversionDict = {
'mm' : lambda x : x * 10.0},
'mm' : {'inch' : lambda x : x * .0393700787,
'cm' : lambda x : x * 0.10},
'meter' : {'foot' : lambda x : x * 3.2808399 } }
'meter' : {'foot' : lambda x : x * 3.2808399 },
'dublin_jd' : {'unix_epoch' : lambda x : (x-25567.5) * 86400.0},
'unix_epoch' : {'dublin_jd' : lambda x : x/86400.0 + 25567.5}}
# Default unit formatting to be used in the absence of a skin configuration file
@@ -237,12 +239,14 @@ default_unit_label_dict = { "centibar" : " cb",
# Default strftime formatting to be used in the absence of a skin
# configuration file:
default_time_format_dict = {"day" : "%H:%M",
"week" : "%H:%M on %A",
"month" : "%d-%b-%Y %H:%M",
"year" : "%d-%b-%Y %H:%M",
"rainyear" : "%d-%b-%Y %H:%M",
"current" : "%d-%b-%Y %H:%M"}
default_time_format_dict = {"day" : "%H:%M",
"week" : "%H:%M on %A",
"month" : "%d-%b-%Y %H:%M",
"year" : "%d-%b-%Y %H:%M",
"rainyear" : "%d-%b-%Y %H:%M",
"current" : "%d-%b-%Y %H:%M",
"ephem_day" : "%H:%M",
"ephem_year" : "%d-%b-%Y %H:%M"}
#===============================================================================
@@ -299,6 +303,9 @@ class Formatter(object):
self.unit_format_dict = unit_format_dict
self.unit_label_dict = unit_label_dict
self.time_format_dict = time_format_dict
# Add new keys for backwards compatibility on old skin dictionaries:
self.time_format_dict.setdefault('ephem_day', "%H:%M")
self.time_format_dict.setdefault('ephem_year', "%d-%b-%Y %H:%M")
@staticmethod
def fromSkinDict(skin_dict):
@@ -336,7 +343,7 @@ class Formatter(object):
if useThisFormat:
val_str = time.strftime(useThisFormat, time.localtime(val_t[0]))
else:
val_str = time.strftime(self.time_format_dict[context], time.localtime(val_t[0]))
val_str = time.strftime(self.time_format_dict.get(context, "%d-%b-%Y %H:%M"), time.localtime(val_t[0]))
except (KeyError, TypeError):
# If all else fails, use this weeutil utility:
val_str = weeutil.weeutil.timestamp_to_string(val_t[0])

View File

@@ -781,6 +781,45 @@ December: Min, max temperatures: N/A N/A
<p>See the NOAA template files <span class="code">NOAA/NOAA-YYYY.txt.tmpl</span>
and <span class="code">NOAA/NOAA-YYYY-MM.txt.tmpl</span> for examples using
iteration, as well as explicit formatting.</p>
<h3>Almanac</h3>
<p>If module <a href="http://rhodesmill.org/pyephem">pyephem</a> has been
installed, then <span class="code">weewx</span> can generate extensive
almanac information for the Sun, Moon, Venus, Mars, and Jupiter, including
their rise, transit and set times, as well as their azimuth and altitude.
Other information is also available. </p>
<p>Here is a small sampling:</p>
<pre>&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Almanac data&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;Current time is $current.dateTime&lt;p&gt;
#if $almanac.hasExtras
&lt;p&gt;Sunrise, transit, sunset: $almanac.sun.rise $almanac.sun.transit $almanac.sun.set&lt;/p&gt;
&lt;p&gt;Moonrise, transit, moonset: $almanac.moon.rise $almanac.moon.transit $almanac.moon.set&lt;/p&gt;
&lt;p&gt;Mars rise, transit, set: $almanac.mars.rise $almanac.mars.transit $almanac.mars.set&lt;/p&gt;
&lt;p&gt;Azimuth, altitude of mars: $almanac.mars.az $almanac.mars.alt&lt;/p&gt;
&lt;p&gt;Next new, full moon: $almanac.next_new_moon $almanac.next_full_moon&lt;/p&gt;
&lt;p&gt;Next summer, winter solstice: $almanac.next_summer_solstice $almanac.next_winter_solstice&lt;/p&gt;
#else
&lt;p&gt;Sunrise, sunset: $almanac.sunrise $almanac.sunset&lt;/p&gt;
#end if
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>If your installation has pyephem installed this would result in:</p>
<pre>Current time is 29-Mar-2011 09:20
Sunrise, transit, sunset: 06:51 13:11 19:30
Moonrise, transit, moonset: 04:33 09:44 15:04
Mars rise, transit, set: 06:35 12:30 18:26
Azimuth, altitude of mars: 124.354959275 26.4808431952
Next new, full moon: 03-Apr-2011 07:32 17-Apr-2011 19:43
Next summer, winter solstice: 21-Jun-2011 10:16 21-Dec-2011 21:29</pre>
<p>Otherwise, a fallback position is used, resulting in</p>
<pre>Current time is 29-Mar-2011 09:20
Sunrise, sunset: 06:51 19:30
</pre>
<p>As shown in the example, you can test whether this extended almanac information is available with
the value <span class="code">$almanac.hasExtras</span>.</p>
<h2>Writing a custom generator</h2>
<p>To do more sophisticated customization it may be necessary to extend an existing
generator, or write your own. </p>
@@ -1039,6 +1078,13 @@ month = %d-%b-%Y %H:%M</pre>
<p>would specify that week data should use a format such as &quot;<span class="code">15:20
on Sunday</span>&quot;, while month data should look like &quot;<span class="code">06-Oct-2009
15:20</span>&quot;</p>
<p>It also allows the formatting to be set for almanac times:</p>
<pre>ephem_day = %H:%M
ephem_year = %d-%b-%Y %H:%M</pre>
<p>The first of these, <span class="code">ephem_day</span>, is used for
almanac times within the day, such as sunrise or sunset. The second,
<span class="code">ephem_year</span>, is used for almanac times within the
year, such as the next equinox or full moon.</p>
<h3 class="config_section">[[DegreeDays]] </h3>
<p class="config_important">heating_base<br />
cooling_base</p>

View File

@@ -99,7 +99,7 @@ Version 1.10</h1>
<h1><a name="Prerequisites">Prerequisites</a></h1>
<h2>Python</h2>
<p>Python V2.5 or V2.6 is required. The newer V3.0 distribution will not work.</p>
<h2>Required packages</h2>
<h2>External packages</h2>
<p>The following external packages are required to use <span class="code">weewx</span>.</p>
<ol>
<li><a href="http://www.sqlite.org/">sqlite3</a> (Version 3.5 or greater)
@@ -118,6 +118,13 @@ Version 1.10</h1>
(Version 1.1.6 or greater) Also known as PIL, this is included in many Python
distributions.</li>
</ol>
<p>In addition, there is one optional package:</p>
<ul>
<li><a href="http://rhodesmill.org/pyephem">pyephem</a> (Version V3.7.3
or greater). For extended almanac information. If not installed,
fallback information will be used. As of the time of this writing, this
package could only be installed using <span class="code">easy_install</span>.</li>
</ul>
<p>There are two general strategies for installing these prerequisites:</p>
<ol>
<li>Use operating system tools, such as <span class="code">apt-get</span>
@@ -127,7 +134,11 @@ Version 1.10</h1>
<a href="http://pypi.python.org/pypi/setuptools">easy_install</a></span>.</li>
</ol>
<p>Option #1 is easier, but if your Linux distribution does not come with such
tools, you may have to use <span class="code">easy_install</span>. Brief instructions
tools, you may have to use <span class="code">easy_install</span>. If you
choose to install <a href="http://rhodesmill.org/pyephem">pyephem</a>, then
it can only be installed using <span class="code">easy_install</span> (<a href="#Installing_pyephem">see
instructions below</a>).</p>
<p>Brief instructions
for both approaches are given below.</p>
<h3>Installation on Debian distributions (including Ubuntu) using
<span class="code">apt-get</span></h3>
@@ -214,6 +225,9 @@ Version 1.10</h1>
<p>My version of Python came with V1.1.6, which works great, but if you need
to install</p>
<pre>easy_install pil</pre>
<p><a name="Installing_pyephem"></a>If you choose to install the optional
package pyephem:</p>
<pre>easy_install pyephem</pre>
<h2>System requirements</h2>
<p>I run <span class="code">weewx</span> on a 500MHz system with an AMD Geode
processor and 512 MB of memory.&nbsp; Configured this way, it consumes about

View File

@@ -175,6 +175,8 @@ class My_install_data(install_data):
new_config = configobj.ConfigObj(f)
new_config.indent_type = ' '
new_version_number = VERSION.split('.')
if len(new_version_number[1]) < 2:
new_version_number[1] = '0'+new_version_number[1]
# Sometimes I forget to turn the debug flag off:
new_config['debug'] = 0
@@ -192,10 +194,14 @@ class My_install_data(install_data):
# assume a very old version:
if not old_version: old_version = '1.0.0'
old_version_number = old_version.split('.')
# Take care of the collation problem when comparing things like
# version '1.9' to '1.10' by prepending a '0' to the former:
if len(old_version_number[1]) < 2:
old_version_number[1] = '0'+old_version_number[1]
# If the user has a version >= 1.7, then merge in the old
# config file.
if old_version_number[0:2] >= ['1','7']:
if old_version_number[0:2] >= ['1','07']:
# Any user changes in old_config will overwrite values in new_config
# with this merge
new_config.merge(old_config)

View File

@@ -2,7 +2,6 @@
## $Revision$
## $Author$
## $Date$
#set $short_time time.strftime("%H:%M"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head profile="http://www.w3.org/2005/10/profile">
@@ -321,66 +320,93 @@
<div class="header">
Today's Almanac
</div>
<table>
<caption class="caption">Sun</caption>
<tr>
<td class="label">Sunrise:</td>
<td class="data">$almanac.sunrise</td>
</tr>
#if $almanac.hasExtras
<tr>
<td class="label">Transit:</td>
<td class="data">$almanac.sun.transit</td>
</tr>
#end if
<tr>
<td class="label">Sunset:</td>
<td class="data">$almanac.sunset</td>
</tr>
#if $almanac.hasExtras
#set $sun_az = "%.1f&deg;" % $almanac.sun.az
#set $sun_alt= "%.1f&deg;" % $almanac.sun.alt
<tr>
<td class="label">Azimuth:</td>
<td class="data">$sun_az</td>
</tr>
<tr>
<td class="label">Altitude:</td>
<td class="data">$sun_alt</td>
</tr>
#end if
</table>
<table>
<caption class="caption">Moon</caption>
<tr>
<td class="label">Phase:</td>
<td class="data">$almanac.moon_phase ($almanac.moon_fullness% full)</td>
</tr>
#if $almanac.hasExtras
<tr>
<td class="label">Rise:</td>
<td class="data">$almanac.moon.rise
</tr>
<tr>
<td class="label">Transit:</td>
<td class="data">$almanac.moon.transit
</tr>
<tr>
<td class="label">Set:</td>
<td class="data">$almanac.moon.set
</tr>
#set $moon_az = "%.1f&deg;" % $almanac.moon.az
#set $moon_alt= "%.1f&deg;" % $almanac.moon.alt
<tr>
<td class="label">Azimuth:</td>
<td class="data">$moon_az</td>
</tr>
<tr>
<td class="label">Altitude:</td>
<td class="data">$moon_alt</td>
</tr>
#end if
</table>
<div class="celestial_group">
<div class="celestial_body">
<table>
<caption class="caption">Sun</caption>
#if $almanac.hasExtras
<tr>
<td class="label">Sunrise:</td>
<td class="data">$almanac.sun.rise</td>
</tr>
<tr>
<td class="label">Transit:</td>
<td class="data">$almanac.sun.transit</td>
</tr>
<tr>
<td class="label">Sunset:</td>
<td class="data">$almanac.sun.set</td>
</tr>
#else
<tr>
<td class="label">Sunrise:</td>
<td class="data">$almanac.sunrise</td>
</tr>
<tr>
<td class="label">Sunset:</td>
<td class="data">$almanac.sunset</td>
</tr>
#end if
#if $almanac.hasExtras
<tr>
<td class="label">Azimuth:</td>
<td class="data">$("%.1f&deg;" % $almanac.sun.az)</td>
</tr>
<tr>
<td class="label">Altitude:</td>
<td class="data">$("%.1f&deg;" % $almanac.sun.alt)</td>
</tr>
<tr>
<td class="label">Equinox:</td>
<td class="data">$almanac.next_equinox
</tr>
<tr>
<td class="label">Solstice:</td>
<td class="data">$almanac.next_solstice
</tr>
#end if
</table>
</div> <!-- end class "celestial_body" -->
<div class="celestial_body">
<table>
<caption class="caption">Moon</caption>
#if $almanac.hasExtras
<tr>
<td class="label">Rise:</td>
<td class="data">$almanac.moon.rise
</tr>
<tr>
<td class="label">Transit:</td>
<td class="data">$almanac.moon.transit
</tr>
<tr>
<td class="label">Set:</td>
<td class="data">$almanac.moon.set
</tr>
<tr>
<td class="label">Azimuth:</td>
<td class="data">$("%.1f&deg;" % $almanac.moon.az)</td>
</tr>
<tr>
<td class="label">Altitude:</td>
<td class="data">$("%.1f&deg;" % $almanac.moon.alt)</td>
</tr>
<tr>
<td class="label">Full moon:</td>
<td class="data">$almanac.next_full_moon
</tr>
<tr>
<td class="label">New moon:</td>
<td class="data">$almanac.next_new_moon
</tr>
#end if
<tr>
<td class="label">Phase:</td>
<td class="data">$almanac.moon_phase<br/>($almanac.moon_fullness% full)</td>
</tr>
</table>
</div> <!-- end class "celestial_body" -->
</div> <!-- end class "celestial_group" -->
</div> <!-- end id "almanac" -->
<div id="plots">

View File

@@ -136,12 +136,14 @@
# This section sets the string format to be used
# each time scale.
#
day = %H:%M
week = %H:%M on %A
month = %d-%b-%Y %H:%M
year = %d-%b-%Y %H:%M
rainyear = %d-%b-%Y %H:%M
current = %d-%b-%Y %H:%M
day = %H:%M
week = %H:%M on %A
month = %d-%b-%Y %H:%M
year = %d-%b-%Y %H:%M
rainyear = %d-%b-%Y %H:%M
current = %d-%b-%Y %H:%M
ephem_day = %H:%M
ephem_year = %d-%b-%Y %H:%M
[[DegreeDays]]
#

View File

@@ -102,6 +102,189 @@ body {
text-align: center;
}
#content .header {
font-size: 14pt;
font-weight: bolder;
color: #3d6c87;
margin-bottom: 10px;
}
#content .caption {
font-weight: bold;
color: #3d6c87;
}
#content .label {
text-align: right;
font-style: italic;
}
#content .data {
text-align: left;
}
#about, #almanac {
margin-bottom: 30px;
}
#almanac {
width:80%;
margin-left: auto;
margin-right: auto;
}
.celestial_group {
}
.celestial_body {
width: 48%;
vertical-align: top;
}
#plots {
width: 90%;
display: block;
margin-left: auto;
margin-right: auto;
}
#plots img {
margin: 3px;
border: thin solid #3d6c87;
padding: 3px;
}
#radar_img {
width: 90%;
display: block;
margin-left: auto;
margin-right: auto;
}
#radar_img img {
width: 90%;
padding: 3px;
margin: 3px;
}
/*
* Navigation bar (week, month, etc.) at the bottom
*/
#navbar {
margin: 0 1% 1% 1%;
padding: 5px;
text-align: center;
clear: both;
border-top: 1px solid #dcdcdc;
border-right: 1px solid #a9a9a9;
border-bottom: 1px solid #808080;
border-left: 1px solid #a9a9a9;
background-color: #fafaff;
}
/*************** Global Styles ***************/
h2, h3, h4, h5, h6 {
color: #3d6c87;
}
body {
margin: 0;
padding: 0;
border: 0;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10pt;
background-color: #f2f2f7;
background-image: url('backgrounds/band.gif');
background-repeat: repeat;
background-attachment: scroll;
}
#container {
margin: 0;
padding: 0;
border: 0;
}
/*
* This is the big header at the top of the page
*/
#masthead {
margin: 1% 1% 0 1%;
padding: 5px;
text-align: center;
border-top: 1px solid #dcdcdc;
border-right: 1px solid #a9a9a9;
border-bottom: 1px solid #808080;
border-left: 1px solid #a9a9a9;
background-color: #fafaff;
}
#masthead h1 {
color: #3d6c87;
}
#masthead h3 {
color: #5f8ea9;
}
/*
* This holds the statistics (daily high/low, etc.) on the left:
*/
#stats_group {
width: 30%;
min-height: 500px;
margin: 1%;
padding: 5px;
float: left;
border-top: 1px solid #dcdcdc;
border-right: 1px solid #a9a9a9;
border-bottom: 1px solid #808080;
border-left: 1px solid #a9a9a9;
background-color: #fafaff;
}
.stats table {
border: thin solid #000000;
width: 100%;
}
.stats td {
border: thin solid #000000;
padding: 2px;
}
.stats_header {
background-color: #000000;
color: #a8b8c8;
font-size: 14pt;
font-weight: bolder;
}
.stats_label {
color: green;
}
.stats_data {
color: red;
}
/*
* This holds the "About", "Almanac", and plots on the right
*/
#content {
width: 62%;
min-height: 500px;
margin: 1%;
padding: 5px;
float: right;
border-top: 1px solid #dcdcdc;
border-right: 1px solid #a9a9a9;
border-bottom: 1px solid #808080;
border-left: 1px solid #a9a9a9;
background-color: #fafaff;
text-align: center;
}
#content .header {
text-align: center;
font-size: 14pt;
@@ -122,35 +305,38 @@ body {
#content td {
width: 50%;
padding: 0;
margin: 0;
}
#content .label {
text-align: right;
font-style: italic;
padding-right: 2px;
}
#content .data {
text-align: left;
padding-left: 2px;
}
#about, #almanac {
margin-bottom: 30px;
}
.celestial_group {
#almanac {
# border: thin solid #3d6c87;
width:60%;
margin-left: auto;
margin-right: auto;
}
.celestial_group {
}
.celestial_body {
width: 48%;
# border: thin solid #3d6c87;
border-top: 1px solid #3d6c87;
border-left:1px solid #3d6c87;
border-bottom: 2px solid #3d6c87;
border-right: 2px solid #3d6c87;
# border-top: 1px solid #3d6c87;
# border-left:1px solid #3d6c87;
# border-bottom: 2px solid #3d6c87;
# border-right: 2px solid #3d6c87;
display:inline-block;
vertical-align: top;
}
@@ -201,4 +387,3 @@ body {
h2, h3, h4, h5, h6 {
color: #3d6c87;
}

View File

@@ -29,7 +29,7 @@ debug = 0
socket_timeout = 20
# Current version
version = 1.10.0a6
version = 1.10.0
############################################################################################