Catch up with main trunk.

This commit is contained in:
Tom Keffer
2014-07-31 01:28:31 +00:00
32 changed files with 1101 additions and 821 deletions

View File

@@ -50,15 +50,16 @@ bin/weewx/uwxutils.py
bin/weewx/wxengine.py
bin/weewx/wxformulas.py
bin/weewx/drivers/__init__.py
bin/weewx/drivers/ads.py
bin/weewx/drivers/cc3000.py
bin/weewx/drivers/fousb.py
bin/weewx/drivers/peetbros.py
bin/weewx/drivers/simulator.py
bin/weewx/drivers/te923.py
bin/weewx/drivers/ultimeter.py
bin/weewx/drivers/vantage.py
bin/weewx/drivers/wmr100.py
bin/weewx/drivers/wmr200.py
bin/weewx/drivers/wmr9x8.py
bin/weewx/drivers/ws1.py
bin/weewx/drivers/ws23xx.py
bin/weewx/drivers/ws28xx.py
docs/changes.txt

View File

@@ -330,7 +330,7 @@ def set_rain_year_start(station, rain_year_start):
def set_time(station):
print "Setting time on console..."
station.setTime(time.time())
station.setTime()
newtime_ts = station.getTime()
print "Current console time is %s" % weeutil.weeutil.timestamp_to_string(newtime_ts)

View File

@@ -132,15 +132,13 @@ def setclock(station, prompt):
v = station.getTime()
vstr = weeutil.weeutil.timestamp_to_string(v)
print "Station clock is", vstr
now = int(time.time() + 0.5)
nstr = weeutil.weeutil.timestamp_to_string(now)
if prompt:
ans = raw_input("Set station clock to %s (y/n)? " % nstr)
ans = raw_input("Set station clock (y/n)? ")
else:
print "Setting station clock to %s" % nstr
print "Setting station clock"
ans = 'y'
if ans == 'y' :
station.setTime(now)
station.setTime()
v = station.getTime()
vstr = weeutil.weeutil.timestamp_to_string(v)
print "Station clock is now", vstr

View File

@@ -23,6 +23,7 @@ issues between weather station console and transceiver.
import optparse
import syslog
import time
import sys
import weewx.drivers.ws28xx
import weewx.units
@@ -49,16 +50,18 @@ def main():
help="pair the USB transceiver with a station console")
parser.add_option("--info", dest="info", action="store_true",
help="display weather station configuration")
parser.add_option("--set-interval", dest="interval", type=int, metavar="N",
help="set logging interval to N minutes")
parser.add_option("--current", dest="current", action="store_true",
help="get the current weather conditions")
parser.add_option("--history-since", dest="recmin", type=int, metavar="N",
help="display history records since N minutes ago")
parser.add_option("--history", dest="nrecords", type=int, metavar="N",
help="display N history records")
parser.add_option("--format", dest="format", type=str, metavar="FORMAT",
help="format for history, one of raw, table, or dict")
parser.add_option("--maxtries", dest="maxtries", type=int,
help="maximum number of retries, 0 indicates no max")
parser.add_option("-y", dest="noprompt", action="store_true",
help="answer yes to every prompt")
parser.add_option("--debug", dest="debug", action="store_true",
help="display diagnostic information while running")
@@ -75,26 +78,25 @@ def main():
station = weewx.drivers.ws28xx.WS28xx(altitude=altitude_m,
**config_dict['WS28xx'])
if options.format is None:
options.format = 'table'
elif (options.format.lower() != 'raw' and
options.format.lower() != 'table' and
options.format.lower() != 'dict'):
print "Unknown format '%s'. Known formats include 'raw', 'table', and 'dict'." % options.format
exit(1)
if options.noprompt:
prompt = False
else:
prompt = True
maxtries = 3 if options.maxtries is None else int(options.maxtries)
if options.check:
check_transceiver(station, maxtries)
elif options.pair:
pair(station, maxtries)
elif options.interval is not None:
set_interval(station, maxtries, options.interval, prompt)
elif options.current:
current(station, maxtries)
elif options.nrecords is not None:
history(station, maxtries, count=options.nrecords, fmt=options.format)
history(station, maxtries, count=options.nrecords)
elif options.recmin is not None:
ts = int(time.time()) - options.recmin * 60
history(station, maxtries, ts=ts, fmt=options.format)
history(station, maxtries, ts=ts)
else:
info(station, maxtries)
@@ -106,139 +108,157 @@ def check_transceiver(station, maxtries):
"""See if the transceiver is installed and operational."""
print 'Checking for transceiver...'
ntries = 0
try:
while ntries < maxtries:
ntries += 1
if station.transceiver_is_present():
print 'Transceiver is present'
sn = station.transceiver_serial()
print 'serial: ' % sn
tid = station.transceiver_id()
print 'id: %d (0x%04x)' % (tid, tid)
break
print 'Not found (attempt %d of %d) ...' % (ntries, maxtries)
time.sleep(5)
else:
print 'Transceiver not responding.'
except Exception, e:
pass
while ntries < maxtries:
ntries += 1
if station.transceiver_is_present():
print 'Transceiver is present'
sn = station.get_transceiver_serial()
print 'serial: %s' % sn
tid = station.get_transceiver_id()
print 'id: %d (0x%04x)' % (tid, tid)
break
print 'Not found (attempt %d of %d) ...' % (ntries, maxtries)
time.sleep(5)
else:
print 'Transceiver not responding.'
def pair(station, maxtries):
"""Pair the transceiver with the station console."""
print 'Pairing transceiver with console...'
maxwait = 90 # how long to wait between button presses, in seconds
ntries = 0
try:
while ntries < maxtries or maxtries == 0:
if station.transceiver_is_paired():
print 'Transceiver is paired to console'
break
ntries += 1
msg = 'Press and hold the [v] key until "PC" appears'
if maxtries > 0:
msg += ' (attempt %d of %d)' % (ntries, maxtries)
else:
msg += ' (attempt %d)' % ntries
print msg
now = start_ts = int(time.time())
while now - start_ts < maxwait and not station.transceiver_is_paired():
time.sleep(5)
now = int(time.time())
while ntries < maxtries or maxtries == 0:
if station.transceiver_is_paired():
print 'Transceiver is paired to console'
break
ntries += 1
msg = 'Press and hold the [v] key until "PC" appears'
if maxtries > 0:
msg += ' (attempt %d of %d)' % (ntries, maxtries)
else:
print 'Transceiver not paired to console.'
except Exception, e:
pass
msg += ' (attempt %d)' % ntries
print msg
now = start_ts = int(time.time())
while now - start_ts < maxwait and not station.transceiver_is_paired():
time.sleep(5)
now = int(time.time())
else:
print 'Transceiver not paired to console.'
def get_interval(station, maxtries):
cfg = get_config(station, maxtries)
if cfg is None:
return None
return weewx.drivers.ws28xx.getHistoryInterval(cfg['history_interval'])
def get_config(station, maxtries):
start_ts = None
ntries = 0
while ntries < maxtries or maxtries == 0:
cfg = station.get_config()
if cfg is not None:
return cfg
ntries += 1
if start_ts is None:
start_ts = int(time.time())
else:
dur = int(time.time()) - start_ts
print 'No data after %d seconds (press SET to sync)' % dur
time.sleep(30)
return None
def set_interval(station, maxtries, interval, prompt):
"""Set the station archive interval"""
print 'Querying the station...'
v = get_interval(station, maxtries)
if v is None:
return
ans = None
while ans not in ['y', 'n']:
print "Interval is", v
if prompt:
ans = raw_input("Set interval to %d minutes (y/n)? " % interval)
else:
print "Setting interval to %d minutes" % interval
ans = 'y'
if ans == 'y' :
station.set_interval(interval)
v = get_interval(station, maxtries)
if v is None:
print "Cannot confirm change of interval"
return
print "Interval is now", v
elif ans == 'n':
print "Set interval cancelled."
def info(station, maxtries):
"""Query the station then display the settings."""
print 'Querying the station for the configuration...'
start_ts = None
ntries = 0
try:
while ntries < maxtries or maxtries == 0:
config = station.get_config()
if config is not None:
print_dict(config)
break
if start_ts is None:
start_ts = int(time.time())
else:
dur = int(time.time()) - start_ts
print 'No data after %d seconds (press SET to sync)' % dur
time.sleep(30)
except Exception:
pass
cfg = get_config(station, maxtries)
if cfg is not None:
print_dict(cfg)
def current(station, maxtries):
"""Get current weather observation."""
print 'Querying the station for current weather data...'
start_ts = None
ntries = 0
try:
while ntries < maxtries or maxtries == 0:
packet = station.get_observation()
if packet is not None:
print_dict(packet)
break
if start_ts is None:
start_ts = int(time.time())
else:
dur = int(time.time()) - start_ts
print 'No data after %d seconds (press SET to sync)' % dur
time.sleep(30)
except Exception:
pass
while ntries < maxtries or maxtries == 0:
packet = station.get_observation()
if packet is not None:
print_dict(packet)
break
ntries += 1
if start_ts is None:
start_ts = int(time.time())
else:
dur = int(time.time()) - start_ts
print 'No data after %d seconds (press SET to sync)' % dur
time.sleep(30)
def history(station, maxtries, ts=0, count=0, fmt='raw'):
def history(station, maxtries, ts=0, count=0):
"""Display the indicated number of records or the records since the
specified timestamp (local time, in seconds)"""
print "Querying the station for historical records..."
records = []
start_ts = None
ntries = 0
try:
while ntries < maxtries or maxtries == 0:
records = station.get_history(since_ts=ts, num_rec=count)
if records is not None:
break
if start_ts is None:
start_ts = int(time.time())
else:
dur = int(time.time()) - start_ts
print 'No data after %d seconds (press SET to sync)' % dur
time.sleep(30)
except Exception:
pass
for i,r in enumerate(records):
if fmt.lower() == 'raw':
raw_dump(r['datetime'], r['ptr'], r['raw_data'])
elif fmt.lower() == 'table':
table_dump(r['datetime'], r['data'], i==0)
last_n = n = None
last_ts = now = int(time.time())
station.start_caching_history(since_ts=ts)
t = weewx.drivers.ws28xx.WS28xx.max_records
while n is None or n > 0:
if ntries >= maxtries:
print 'Giving up after %d tries' % ntries
break
time.sleep(30)
now = int(time.time())
n = station.get_num_history_scanned()
if n == last_n:
ntries += 1
dur = now - last_ts
print 'No data after %d seconds (press SET to sync)' % dur
else:
print r['datetime'], r['data']
def raw_dump(date, pos, data):
print date,
print "%04x" % pos,
for item in data:
print "%02x" % item,
print
def table_dump(date, data, showlabels=False):
if showlabels:
print '# date time',
for key in data:
print key,
print
print date,
for key in data:
print data[key],
ntries = 0
last_ts = now
last_n = n
ni = station.get_next_history_index()
li = station.get_latest_history_index()
msg = " scanned %s of %s: current=%s latest=%s\r" % (n, t, ni, li)
sys.stdout.write(msg)
sys.stdout.flush()
station.stop_caching_history()
records = station.get_history_cache_records()
station.clear_history_cache()
print
print 'Found a total of %d records' % len(records)
for r in records:
print r
def print_dict(data):
for key in sorted(data, key=data.get):
print '%s: %s' % (key, data[key])
for x in sorted(data.keys()):
if x == 'dateTime':
print '%s: %s' % (x, weeutil.weeutil.timestamp_to_string(data[x]))
else:
print '%s: %s' % (x, data[x])
if __name__=="__main__" :

View File

@@ -32,7 +32,7 @@ class AbstractStation(object):
def getTime(self):
raise NotImplementedError("Method 'getTime' not implemented")
def setTime(self, newtime_ts):
def setTime(self):
raise NotImplementedError("Method 'setTime' not implemented")
def closePort(self):

View File

@@ -24,6 +24,7 @@ catchup on startup.
from __future__ import with_statement
import serial
import string
import syslog
import time
@@ -37,7 +38,7 @@ INHG_PER_MBAR = 0.0295333727
METER_PER_FOOT = 0.3048
MILE_PER_KM = 0.621371
DRIVER_VERSION = '0.6'
DRIVER_VERSION = '0.7'
DEFAULT_PORT = '/dev/ttyS0'
def logmsg(level, msg):
@@ -67,18 +68,20 @@ class CC3000(weewx.abstractstation.AbstractStation):
'''weewx driver that communicates with a RainWise CC3000 data logger.'''
# map rainwise names to weewx names
LABEL_MAP = { 'TIMESTAMP': 'TIMESTAMP',
'TEMP OUT': 'outTemp',
'HUMIDITY': 'outHumidity',
'WIND DIRECTION': 'windDir',
'WIND SPEED': 'windSpeed',
'WIND GUST': 'windGust',
'PRESSURE': 'pressure',
'TEMP IN': 'inTemp',
'RAIN': 'day_rain_total',
'STATION BATTERY': 'consBatteryVoltage',
'BATTERY BACKUP': 'bkupBatteryVoltage',
}
DEFAULT_LABEL_MAP = { 'TIMESTAMP': 'TIMESTAMP',
'TEMP OUT': 'outTemp',
'HUMIDITY': 'outHumidity',
'WIND DIRECTION': 'windDir',
'WIND SPEED': 'windSpeed',
'WIND GUST': 'windGust',
'PRESSURE': 'pressure',
'TEMP IN': 'inTemp',
'RAIN': 'day_rain_total',
'STATION BATTERY': 'consBatteryVoltage',
'BATTERY BACKUP': 'bkupBatteryVoltage',
'SOLAR RADIATION': 'radiation',
'UV INDEX': 'UV',
}
def __init__(self, **stn_dict):
self.altitude = stn_dict['altitude']
@@ -91,6 +94,7 @@ class CC3000(weewx.abstractstation.AbstractStation):
self.use_station_time = stn_dict.get('use_station_time', True)
self.max_tries = int(stn_dict.get('max_tries', 5))
self.retry_wait = int(stn_dict.get('retry_wait', 60))
self.label_map = stn_dict.get('label_map', self.DEFAULT_LABEL_MAP)
self.last_rain = None
@@ -165,9 +169,9 @@ class CC3000(weewx.abstractstation.AbstractStation):
v = station.get_time()
return _to_ts(v)
def setTime(self, ts):
def setTime(self):
with Station(self.port) as station:
station.set_time(ts)
station.set_time()
def get_current(self):
with Station(self.port) as station:
@@ -299,7 +303,7 @@ class CC3000(weewx.abstractstation.AbstractStation):
for i,v in enumerate(values):
if i >= len(self.header):
continue
label = self.LABEL_MAP.get(self.header[i])
label = self.label_map.get(self.header[i])
if label is None:
continue
if label == 'TIMESTAMP':
@@ -323,6 +327,9 @@ def _to_ts(tstr, fmt="%Y/%m/%d %H:%M:%S"):
def _format_bytes(buf):
return ' '.join(["%0.2X" % ord(c) for c in buf])
def _fmt(buf):
return filter(lambda x: x in string.printable, buf)
# calculate the crc for a string using CRC-16-CCITT
# http://bytes.com/topic/python/insights/887357-python-check-crc-frame-crc-16-ccitt
def _crc16(data):
@@ -406,11 +413,10 @@ class Station(object):
def command(self, cmd):
self.write("%s\r" % cmd)
data = self.get_data()
logdbg("station replied to command with '%s'" % data)
data = data.strip()
if data != cmd:
raise weewx.WeeWxIOError("Command failed: cmd='%s' data='%s'" %
(cmd, data))
raise weewx.WeeWxIOError("Command failed: cmd='%s' reply='%s' (%s)"
% (cmd, _fmt(data), _format_bytes(data)))
return self.get_data()
def send_cmd(self, cmd):
@@ -433,7 +439,10 @@ class Station(object):
break
else:
raise weewx.WeeWxIOError("Unexpected byte 0x%0.2X" % ord(c))
buf.append(c)
if c in string.printable:
buf.append(c)
else:
loginf("skipping unprintable character 0x%0.2X" % ord(c))
data = ''.join(buf)
logdbg("got bytes: '%s'" % _format_bytes(data))
_check_crc(data)
@@ -443,7 +452,7 @@ class Station(object):
logdbg("set echo to %s" % cmd)
data = self.command('ECHO=%s' % cmd)
if data != 'OK':
raise weewx.WeeWxIOError("Set ECHO failed: %s" % data)
raise weewx.WeeWxIOError("Set ECHO failed: %s" % _fmt(data))
def get_header(self):
data = self.command("HEADER")
@@ -462,13 +471,13 @@ class Station(object):
def get_memory_status(self):
data = self.command("MEM=?")
logdbg("memory status: %s" % data)
logdbg("memory status: %s" % _fmt(data))
return data
def clear_memory(self):
data = self.command("MEM=CLEAR")
if data != 'OK':
raise weewx.WeeWxIOError("Failed to clear memory: %s" % data)
raise weewx.WeeWxIOError("Failed to clear memory: %s" % _fmt(data))
def gen_records(self, nrec):
"""generator function for getting records from the device"""
@@ -499,13 +508,14 @@ class Station(object):
data = self.command("TIME=?")
return data
def set_time(self, ts):
tstr = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(ts))
logdbg("set time to %s (%s)" % (tstr, ts))
def set_time(self):
tstr = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(time.time()))
logdbg("set time to %s (%s)" % (tstr, tstr))
s = "TIME=%s" % tstr
data = self.command(s)
if data != 'OK':
raise weewx.WeeWxIOError("Failed to set time to %s: %s" % (s,data))
raise weewx.WeeWxIOError("Failed to set time to %s: %s" %
(s, _fmt(data)))
def get_units(self):
data = self.command("UNITS=?")
@@ -516,7 +526,7 @@ class Station(object):
data = self.command("UNITS=%s" % units)
if data != 'OK':
raise weewx.WeeWxIOError("Failed to set units to %s: %s" %
(units, data))
(units, _fmt(data)))
def get_interval(self):
data = self.command("LOGINT=?")
@@ -527,7 +537,7 @@ class Station(object):
data = self.command("LOGINT=%d" % interval)
if data != 'OK':
raise weewx.WeeWxIOError("Failed to set logging interval: %s" %
data)
_fmt(data))
def get_version(self):
data = self.command("VERSION")
@@ -607,7 +617,7 @@ if __name__ == '__main__':
if options.gettime:
print s.get_time()
if options.settime:
s.set_time(time.time())
s.set_time()
if options.getint:
print s.get_interval()
if options.setint:

View File

@@ -151,6 +151,20 @@ specified in weewx.conf, and 'temperature' is read from the sensors.
The 'barometer' value is reported to wunderground, cwop, etc.
Illuminance and Radiation
The 30xx stations include a sensor that reports illuminance (lux). The
conversion from lux to radiation is a function of the angle of the sun and
altitude, but this driver uses a single multiplier as an approximation.
Apparently the display on fine offset stations is incorrect. The display
reports radiation with a lux-to-W/m^2 multiplier of 0.001464. Apparently
Cumulus and WeatherDisplay use a multiplier of 0.0079. The multiplier for
sea level with sun directly overhead is 0.01075.
This driver uses the sea level multiplier of 0.01075. Use an entry in
StdCalibrate to adjust this for your location and altitude.
From Jim Easterbrook:
The weather station memory has two parts: a "fixed block" of 256 bytes
@@ -260,7 +274,7 @@ keymap = {
'windDir' : ('wind_dir', 22.5), # station is 0-15, weewx wants deg
'windGustDir' : ('wind_dir', 22.5), # station is 0-15, weewx wants deg
'rain' : ('rain', 0.1), # station is mm, weewx wants cm
'radiation' : ('illuminance', 0.001464), # lux, weewx wants W/m^2
'radiation' : ('illuminance', 0.01075), # lux, weewx wants W/m^2
'UV' : ('uv', 1.0),
'dewpoint' : ('dewpoint', 1.0),
'heatindex' : ('heatindex', 1.0),
@@ -410,9 +424,10 @@ def pywws2weewx(p, ts, pressure_offset, altitude,
USB_RT_PORT = (usb.TYPE_CLASS | usb.RECIP_OTHER)
USB_PORT_FEAT_POWER = 8
def power_cycle_station(self, hub, port):
def power_cycle_station(hub, port):
'''Power cycle the port on the specified hub. This works only with USB
hubs that support per-port power switching such as the linksys USB2HUB4.'''
loginf("Attempting to power cycle")
busses = usb.busses()
if not busses:
raise weewx.WeeWxIOError("Power cycle failed: cannot find USB busses")
@@ -432,14 +447,18 @@ def power_cycle_station(self, hub, port):
request=usb.REQ_CLEAR_FEATURE,
value=USB_PORT_FEAT_POWER,
index=port, buffer=None, timeout=1000)
time.sleep(10)
loginf("Waiting 30 seconds for station to power down")
time.sleep(30)
loginf("Power on port %d on hub %s" % (port, hub))
handle.controlMsg(requestType=USB_RT_PORT,
request=usb.REQ_SET_FEATURE,
value=USB_PORT_FEAT_POWER,
index=port, buffer=None, timeout=1000)
loginf("Waiting 60 seconds for station to power up")
time.sleep(60)
finally:
del handle
loginf("Power cycle complete")
# decode weather station raw data formats
def _signed_byte(raw, offset):
@@ -658,6 +677,7 @@ class FineOffsetUSB(weewx.abstractstation.AbstractStation):
# minimum interval between polling for data change
self.min_pause = 0.5
self.devh = None
self._arcint = None
self._last_rain_loop = None
self._last_rain_ts_loop = None
@@ -702,27 +722,39 @@ class FineOffsetUSB(weewx.abstractstation.AbstractStation):
def archive_interval(self):
return self._archive_interval_minutes() * 60
# if power cycling is enabled, loop forever until we get a response from
# the weather station.
def _archive_interval_minutes(self):
if self._arcint is None:
for i in range(self.max_tries):
if self._arcint is not None:
return self._arcint
if self.pc_hub is not None:
while True:
try:
self._arcint = self.get_fixed_block(['read_period'])
self.openPort()
self._get_arcint()
break
except usb.USBError, e:
logcrt("get archive interval failed attempt %d of %d: %s"
% (i+1, self.max_tries, e))
else:
msg = "Unable to read archive interval after %d tries" % self.max_tries
if self.pc_hub is not None:
logerr(msg)
logerr("Attempting to power cycle")
except weewx.WeeWxIOError, e:
self.closePort()
power_cycle_station(self.pc_hub, self.pc_port)
raise weewx.WeeWxIOError("Power cycle complete")
else:
raise weewx.WeeWxIOError(msg)
else:
self._get_arcint()
return self._arcint
def _get_arcint(self):
for i in range(self.max_tries):
try:
self._arcint = self.get_fixed_block(['read_period'])
return
except usb.USBError, e:
logcrt("get archive interval failed attempt %d of %d: %s"
% (i+1, self.max_tries, e))
else:
raise weewx.WeeWxIOError("Unable to read archive interval after %d tries" % self.max_tries)
def openPort(self):
if self.devh is not None:
return
dev = self._find_device()
if not dev:
logcrt("Cannot find USB device with Vendor=0x%04x ProdID=0x%04x Device=%s" % (self.vendor_id, self.product_id, self.device_id))
@@ -770,8 +802,8 @@ class FineOffsetUSB(weewx.abstractstation.AbstractStation):
# def getTime(self):
# return self.get_clock()
# def setTime(self, ts):
# self.set_clock(ts)
# def setTime(self):
# self.set_clock()
def genLoopPackets(self):
"""Generator function that continuously returns decoded packets."""

View File

@@ -186,7 +186,7 @@ class Rain(object):
n_rain_packets = total_rain / Rain.bucket_tip
self.period = int(npackets/n_rain_packets)
self.rain_start = 3600* rain_start
self.rain_end = rain_start + 3600 * rain_length
self.rain_end = self.rain_start + 3600 * rain_length
self.packet_number = 0
def value_at(self, time_ts):

View File

@@ -161,7 +161,7 @@ import weewx.abstractstation
import weewx.units
import weewx.wxformulas
DRIVER_VERSION = '0.9'
DRIVER_VERSION = '0.10'
DEBUG_READ = 0
DEBUG_DECODE = 0
DEBUG_PRESSURE = 0
@@ -674,7 +674,7 @@ class BadRead(weewx.WeeWxIOError):
"""Bogus data length, CRC, header block, or other read failure"""
class Station(object):
ENDPOINT_IN = 0x01
ENDPOINT_IN = 0x81
READ_LENGTH = 0x8
def __init__(self, vendor_id=0x1130, product_id=0x6801,

View File

@@ -14,10 +14,44 @@
#
# See http://www.gnu.org/licenses/
"""Driver for Peet Bros Ultimeter weather stations (except the Ultimeter II).
"""Driver for Peet Bros Ultimeter weather stations (based on the
ADS WS1 driver) except the Ultimeter II (now quite old from early 1990s).
This driver assumes the Ultimeter is emitting data in Peet Bros Data Logger
mode format.
Thanks to Steve (sesykes71) for the testing that made this driver possible.
Thanks to Jay Nugent (WB8TKL) and KRK6 for weather-2.kr6k-V2.1
http://server1.nuge.com/~weather/
To use this driver, put this file in bin/user, then put this in weewx.conf:
[Station]
...
station_type = PeetBros
[PeetBros]
port = /dev/ttyS0
driver = user.peetbros
The driver assumes the Ultimeter is emitting data in Peet Bros Data Logger
mode format:
!!000000BE02EB000027700000023A023A0025005800000000
SSSSXXDDTTTTLLLLPPPPttttHHHHhhhhddddmmmmRRRRWWWW
SSSS - wind speed (0.1 km/h)
XX - wind direction calibration
DD - wind direction (0-255)
TTTT - outdoor temperature (0.1 F)
LLLL - long term rain (0.01 in)
PPPP - pressure (0.1 mbar)
tttt - indoor temperature (0.1 F)
HHHH - outdoor humidity (0.1 %)
hhhh - indoor humidity (0.1 %)
dddd - date (day of year)
mmmm - time (minute of day)
RRRR - daily rain (0.01 in)
WWWW - one minute wind average (0.1 km/h)
Resources for the Ultimeter stations
@@ -27,9 +61,6 @@ Ultimeter Models 2100, 2000, 800, & 100 serial specifications:
Ultimeter 2000 Pinouts and Parsers:
http://www.webaugur.com/ham-radio/52-ultimeter-2000-pinouts-and-parsers.html
Ultimeter II:
not supported by this driver
All models communicate over an RS-232 compatible serial port using three
wires--RXD, TXD, and Ground (except Ultimeter II which omits TXD). Port
parameters are 2400, 8N1, with no flow control.
@@ -40,17 +71,16 @@ and time of the Ultimeter upon initialization and then sets it into Data
Logger mode for continuous updates.
Modem Mode commands used by the driver
>Addddmmmm Set Date and Time (decimal digits dddd = day of year,
mmmm = minute of day; Jan 1 = 0000, Midnight = 0000)
>I Set output mode to Data Logger Mode (continuous output)
"""
# FIXME: eliminate the weewx.XXX classes from the station level
from __future__ import with_statement
import optparse
import serial
import syslog
import time
@@ -61,16 +91,20 @@ import weewx.units
import weewx.uwxutils
import weewx.wxformulas
INHG_PER_MBAR = 0.0295333727
METER_PER_FOOT = 0.3048
MILE_PER_KM = 0.621371
DRIVER_VERSION = '0.11.0'
DRIVER_VERSION = '0.9.4'
DEFAULT_PORT = '/dev/ttyS0'
DEBUG_READ = 1
DEBUG_READ = 0
def _is_hex(c):
"""Test character for a valid hexadecimal digit."""
try:
int(c, 16)
return True
except ValueError:
return False
def logmsg(level, msg):
syslog.syslog(level, 'ultimeter: %s' % msg)
syslog.syslog(level, 'peetbros: %s' % msg)
def logdbg(msg):
logmsg(syslog.LOG_DEBUG, msg)
@@ -81,10 +115,14 @@ def loginf(msg):
def logerr(msg):
logmsg(syslog.LOG_ERR, msg)
def logcrt(msg):
logmsg(syslog.LOG_CRIT, msg)
def loader(config_dict, engine):
"""Get the altitude, in feet, from the Station section of the dict."""
altitude_m = weewx.units.getAltitudeM(config_dict)
altitude_ft = altitude_m / METER_PER_FOOT
altitude_vt = (altitude_m, 'meter', 'group_altitude')
altitude_ft = weewx.units.convert(altitude_vt, 'foot')[0]
station = Ultimeter(altitude=altitude_ft, **config_dict['Ultimeter'])
return station
@@ -94,9 +132,6 @@ class Ultimeter(weewx.abstractstation.AbstractStation):
port - serial port
[Required. Default is /dev/ttyS0]
model - station model, e.g., 'Ultimeter 2000' or 'Ultimeter 100'
[Optional. Default is Ultimeter]
polling_interval - how often to query the serial interface, seconds
[Optional. Default is 1]
@@ -113,65 +148,16 @@ class Ultimeter(weewx.abstractstation.AbstractStation):
self.polling_interval = float(stn_dict.get('polling_interval', 1))
self.max_tries = int(stn_dict.get('max_tries', 5))
self.pressure_offset = float(stn_dict.get('pressure_offset', 0))
self.model = stn_dict.get('model', 'Ultimeter')
self.last_rain = None
self.last_rain_ts = None
loginf('driver version is %s' % DRIVER_VERSION)
loginf('using serial port %s' % self.port)
loginf('polling interval is %s' % self.polling_interval)
loginf('pressure offset is %s' % self.pressure_offset)
loginf('polling interval is %s' % str(self.polling_interval))
global DEBUG_READ
DEBUG_READ = int(stn_dict.get('debug_read', DEBUG_READ))
def getTime(self):
with Station(self.port) as station:
return station.get_time()
def setTime(self, ts):
with Station(self.port) as station:
station.set_time(ts)
def genLoopPackets(self):
return self.glp1()
def glp1(self):
# this version of genLoopPackets does the maxtries at station level
# and keeps the serial port open for an extended time.
with Station(self.port) as station:
station.set_logger_mode()
while True:
buf = station.get_readings_with_retry()
data = Station.parse_readings(buf)
packet = {'dateTime': int(time.time()+0.5),
'usUnits' : weewx.US }
packet.update(data)
self._augment_packet(packet)
yield packet
if self.polling_interval:
time.sleep(self.polling_interval)
def glp2(self):
# this version of genLoopPackets does the maxtries at station level
# and opens the serial port for each data read.
with Station(self.port) as station:
station.set_logger_mode()
while True:
with Station(self.port) as station:
buf = station.get_readings_with_retry()
data = Station.parse_readings(buf)
packet = {'dateTime': int(time.time()+0.5),
'usUnits' : weewx.US }
packet.update(data)
self._augment_packet(packet)
yield packet
if self.polling_interval:
time.sleep(self.polling_interval)
def glp3(self):
# this version of genLoopPackets does the maxtries at driver level
# and opens the serial port for each data read.
ntries = 0
with Station(self.port) as station:
station.set_logger_mode()
while ntries < self.max_tries:
ntries += 1
try:
@@ -179,8 +165,8 @@ class Ultimeter(weewx.abstractstation.AbstractStation):
'usUnits' : weewx.US }
# open a new connection to the station for each reading
with Station(self.port) as station:
buf = station.get_readings()
data = Station.parse_readings(buf)
bytes = station.get_readings()
data = Station.parse_readings(bytes)
packet.update(data)
self._augment_packet(packet)
ntries = 0
@@ -197,17 +183,14 @@ class Ultimeter(weewx.abstractstation.AbstractStation):
@property
def hardware_name(self):
return self.model
return Station.getName()
def _augment_packet(self, packet):
"""add derived metrics to a packet"""
# the ultimeter appears to report a (calculated) sea-level pressure
# rather than a raw station (sensor) pressure. so we must
# back-calculate to find the station pressure.
adjp = packet['barometer']
if self.pressure_offset is not None and adjp is not None:
adjp += self.pressure_offset * INHG_PER_MBAR # convert to inHg
# FIXME: second temperature should be 12-hour mean temperature
adjp += self.pressure_offset * 0.0295333727 # convert to inHg
# FIXME: this is supposed to use mean temperature
packet['pressure'] = weewx.uwxutils.TWxUtilsUS.SeaLevelToStationPressure(adjp, self.altitude, packet['outTemp'], packet['outTemp'], packet['outHumidity'])
packet['altimeter'] = weewx.wxformulas.altimeter_pressure_US(
packet['pressure'], self.altitude, algorithm='aaNOAA')
@@ -225,31 +208,10 @@ class Ultimeter(weewx.abstractstation.AbstractStation):
packet['rain'] = None
self.last_rain = packet['long_term_rain']
# no wind direction when wind speed is zero
if not packet['windSpeed']:
packet['windDir'] = None
def _is_valid_char(c):
'''See whether a character is a valid hexadecimal digit or hyphen.'''
if c == '-':
return True
try:
int(c, 16)
return True
except ValueError:
return False
def _hex2int(s, multiplier=None):
'''Ultimeter puts hyphens in the string when a sensor is not installed.
When we get a hyphen or any other non-hex character, return None.'''
v = None
try:
v = int(s, 16)
if multiplier is not None:
v *= multiplier
except ValueError:
pass
return v
# calculate the rain rate
packet['rainRate'] = weewx.wxformulas.calculate_rain_rate(
packet['rain'], packet['dateTime'], self.last_rain_ts)
self.last_rain_ts = packet['dateTime']
class Station(object):
def __init__(self, port):
@@ -257,7 +219,6 @@ class Station(object):
self.baudrate = 2400
self.timeout = 30
self.serial_port = None
self.max_tries = 5
def __enter__(self):
self.open()
@@ -266,15 +227,30 @@ class Station(object):
def __exit__(self, type, value, traceback):
self.close()
@staticmethod
def getName(self):
return "Ultimeter"
def open(self):
logdbg("open serial port %s" % self.port)
self.serial_port = serial.Serial(self.port, self.baudrate,
timeout=self.timeout)
# self.set_logger_mode()
# Set date and time as internal clock skews.
self.serial_port.write(">A%04d%04d\r"
% (time.localtime().tm_yday - 1, time.localtime().tm_min
+ time.localtime().tm_hour * 60))
# Set to Data Logger Mode
self.serial_port.write(">I\r")
def close(self):
if self.serial_port is not None:
logdbg("close serial port %s" % self.port)
# Set to Modem Mode (stops Data Logger output)
self.serial_port.write(">\r")
self.serial_port.close()
self.serial_port = None
@@ -285,7 +261,7 @@ class Station(object):
raise weewx.WeeWxIOError(e)
n = len(buf)
if n != nchar:
if DEBUG_READ and n:
if DEBUG_READ:
logdbg("partial buffer: '%s'" %
' '.join(["%0.2X" % ord(c) for c in buf]))
raise weewx.WeeWxIOError("Read expected %d chars, got %d" %
@@ -298,86 +274,37 @@ class Station(object):
raise weewx.WeeWxIOError("Write expected %d chars, sent %d" %
(len(data), n))
def flush(self):
logdbg("flush serial buffer")
self.serial_port.flushInput()
def get_time(self):
self.set_logger_mode()
buf = self.get_readings_with_retry()
data = Station.parse_readings(buf)
d = data['day_of_year']
m = data['minute_of_day']
tstr = time.localtime()
y = tstr.tm_year
s = tstr.tm_sec
ts = time.mktime((y,0,0,0,0,s,0,0,0)) + d * 86400 + m * 60
return ts
def set_time(self, ts):
self.set_modem_mode()
tstr = time.localtime(ts)
tcmd = ">A%04d%04d\r" % (
tstr.tm_yday - 1, tstr.tm_min + tstr.tm_hour * 60)
logdbg("set station time to %d (%s)" % (ts, tcmd))
self.write(tcmd)
# year works only for models 2004 and later
y = tstr.tm_year
ycmd = ">U%s" % y
logdbg("set station year to %s (%s)" % (y, ycmd))
self.write(ycmd)
def set_logger_mode(self):
# in logger mode, station sends logger mode records continuously
logdbg("set station to logger mode")
self.write(">I\r")
def set_modem_mode(self):
# modem mode is available only on models 2004 and later
# not available on pre-2004 models 50/100/500/700/800
logdbg("set station to modem mode")
self.write(">\r")
def get_readings_with_retry(self):
ntries = 0
while ntries < self.max_tries:
ntries += 1
try:
return self.get_readings()
except weewx.WeeWxIOError, e:
logerr("Failed attempt %d of %d to get readings: %s" %
(ntries, self.max_tries, e))
else:
msg = "Max retries (%d) exceeded for readings" % self.max_tries
logerr(msg)
raise weewx.RetriesExceeded(msg)
return []
def get_readings(self):
buf = []
bytes = []
while True:
c = self.read(1)
if c == "\r" or c == "\n":
break
elif c == '!' and len(buf) > 0:
elif c == '!' and len(bytes) > 0:
break
elif c == '!':
buf = []
elif _is_valid_char(c):
buf.append(c)
bytes = []
elif c == '-':
# Ultimeter may put hyphens in the string if a sensor
# is not installed. Make the reading zero instead.
bytes.append('0')
elif _is_hex(c) is True:
# Ultimeter uses hexadecimal characters for its values.
# Guard against garbage.
bytes.append(c)
else:
raise weewx.WeeWxIOError("Invalid character %0.2X" % ord(c))
bytes = []
if DEBUG_READ:
logdbg("bytes: '%s'" % ' '.join(["%0.2X" % ord(c) for c in buf]))
if len(buf) != 48:
raise weewx.WeeWxIOError("Got %d bytes, expected 48" % len(buf))
return ''.join(buf)
logdbg("bytes: '%s'" % ' '.join(["%0.2X" % ord(c) for c in bytes]))
if len(bytes) != 48:
raise weewx.WeeWxIOError("Got %d bytes, expected 48" % len(bytes))
return ''.join(bytes)
@staticmethod
def parse_readings(buf):
'''Parse the bytes in data logger format. Each line has 2 header
bytes, 48 data bytes, and a carriage return and newline:
def parse_readings(bytes):
'''Ultimeter stations emit data in PeetBros format. Each line has 52
characters - 2 header bytes, 48 data bytes, and a carriage return
and line feed (new line):
!!000000BE02EB000027700000023A023A0025005800000000\r\n
SSSSXXDDTTTTLLLLPPPPttttHHHHhhhhddddmmmmRRRRWWWW
@@ -396,24 +323,30 @@ class Station(object):
RRRR - daily rain (0.01 in)
WWWW - one minute wind average (0.1 kph)
For date, time, and other non-standard readings use labels that
will not interfere with weewx/wview conventions.
"pressure" reported by the Ultimeter 2000 is correlated to the local
official barometer reading as part of the setup of the station
console so this value is assigned to the 'barometer' key and
the pressure and altimeter values are calculated from it.
My Ultimeter 2000 puts hyphens, '-', in the place of the indoor
humidity (hhhh) since there is no indoor humidty sensor installed.
The driver will identify the hyphens and replace them with the '0'
character.
'''
data = {}
data['windSpeed'] = _hex2int(buf[0:4], 0.1 * MILE_PER_KM) # mph
data['windDir'] = _hex2int(buf[6:8], 1.411764) # compass degrees
data['outTemp'] = _hex2int(buf[8:12], 0.1) # degree_F
data['long_term_rain'] = _hex2int(buf[12:16], 0.01) # inch
data['barometer'] = _hex2int(buf[16:20], 0.1 * INHG_PER_MBAR) # inHg
data['inTemp'] = _hex2int(buf[20:24], 0.1) # degree_F
data['outHumidity'] = _hex2int(buf[24:28], 0.1) # percent
data['inHumidity'] = _hex2int(buf[28:32], 0.1) # percent
data['day_of_year'] = _hex2int(buf[32:36])
data['minute_of_day'] = _hex2int(buf[36:40])
data['daily_rain'] = _hex2int(buf[40:44], 0.01) # inch
data['wind_average'] = _hex2int(buf[44:48], 0.1 * MILE_PER_KM) # mph
data['windSpeed'] = int(bytes[0:4], 16) * 0.1 * 0.621371 # mph
data['windDir'] = int(bytes[6:8], 16) * 1.411764 # compass degrees
data['outTemp'] = int(bytes[8:12], 16) * 0.1 # degree_F
data['long_term_rain'] = int(bytes[12:16], 16) * 0.01 # inch
data['barometer'] = int(bytes[16:20], 16) * 0.1 * 0.0295333727 # inHg
data['inTemp'] = int(bytes[20:24], 16) * 0.1 # degree_F
data['outHumidity'] = int(bytes[24:28], 16) * 0.1 # percent
data['inHumidity'] = int(bytes[28:32], 16) * 0.1 # percent
data['daily_rain'] = int(bytes[40:44], 16) * 0.01 # inch
data['wind_average'] = int(bytes[44:48], 16) * 0.1 * 0.621371 # mph
return data
# define a main entry point for basic testing of the station without weewx
@@ -422,7 +355,6 @@ class Station(object):
# PYTHONPATH=bin python bin/weewx/drivers/ultimeter.py
if __name__ == '__main__':
import optparse
usage = """%prog [options] [--help]"""
@@ -435,26 +367,14 @@ if __name__ == '__main__':
parser.add_option('--port', dest='port', metavar='PORT',
help='serial port to which the station is connected',
default=DEFAULT_PORT)
parser.add_option('--get-current', dest='getcur', action='store_true',
help='display current readings')
parser.add_option('--get-time', dest='gettime', action='store_true',
help='display station time')
(options, args) = parser.parse_args()
if options.version:
print "PeetBros Ultimeter driver version %s" % DRIVER_VERSION
print "ultimeter driver version %s" % DRIVER_VERSION
exit(0)
with Station(options.port) as s:
if options.getcur:
s.set_logger_mode()
buf = s.get_readings_with_retry()
print buf
data = Station.parse_readings(buf)
print data
if options.gettime:
ts = s.get_time()
print ts
print s.get_readings()
if __name__ == '__main__':
main()

View File

@@ -637,24 +637,26 @@ class Vantage(weewx.abstractstation.AbstractStation):
syslog.syslog(syslog.LOG_ERR, "vantage: Max retries exceeded while getting time")
raise weewx.RetriesExceeded("While getting console time")
def setTime(self, newtime_ts):
"""Set the clock on the Davis Vantage console
def setTime(self):
"""Set the clock on the Davis Vantage console"""
newtime_ts: The time the internal clock should be set to in unix epoch time."""
# Unfortunately, this algorithm takes a little while to execute, so the clock
# usually ends up a few hundred milliseconds slow
newtime_tt = time.localtime(int(newtime_ts + 0.5))
# The Davis expects the time in reversed order, and the year is since 1900
_buffer = struct.pack("<bbbbbb", newtime_tt[5], newtime_tt[4], newtime_tt[3], newtime_tt[2],
newtime_tt[1], newtime_tt[0] - 1900)
for unused_count in xrange(self.max_tries) :
try :
# Wake the console and begin the setTime command
self.port.wakeup_console(max_tries=self.max_tries, wait_before_retry=self.wait_before_retry)
self.port.send_data('SETTIME\n')
self.port.send_data_with_crc16(_buffer, max_tries=self.max_tries)
# Unfortunately, clock resolution is only 1 second, and transmission takes a
# little while to complete, so round up the clock up. 0.5 for clock resolution
# and 0.25 for transmission delay
newtime_tt = time.localtime(int(time.time() + 0.75))
# The Davis expects the time in reversed order, and the year is since 1900
_buffer = struct.pack("<bbbbbb", newtime_tt[5], newtime_tt[4], newtime_tt[3], newtime_tt[2],
newtime_tt[1], newtime_tt[0] - 1900)
# Complete the setTime command
self.port.send_data_with_crc16(_buffer, max_tries=1)
syslog.syslog(syslog.LOG_NOTICE,
"vantage: Clock set to %s" % weeutil.weeutil.timestamp_to_string(time.mktime(newtime_tt)))
return

View File

@@ -422,9 +422,9 @@ class WS23xx(weewx.abstractstation.AbstractStation):
# with Station(self.port) as s:
# return s.get_time()
# def setTime(self, ts):
# def setTime(self):
# with Station(self.port) as s:
# s.set_time(ts)
# s.set_time()
def getArchiveInterval(self):
with Station(self.port) as s:

View File

File diff suppressed because it is too large Load Diff

View File

@@ -230,10 +230,12 @@ class RsyncGenerator(ReportGenerator):
# We don't try to collect performance statistics about rsync, because rsync
# will report them for us. Check the debug log messages.
try:
if self.skin_dict.has_key('HTML_ROOT'):
html_root = self.skin_dict['HTML_ROOT']
else:
html_root = self.config_dict['StdReport']['HTML_ROOT']
rsyncData = weeutil.rsyncupload.RsyncUpload(
local_root = os.path.join(
self.config_dict['WEEWX_ROOT'],
self.config_dict['StdReport']['HTML_ROOT']),
local_root = os.path.join(self.config_dict['WEEWX_ROOT'], html_root),
remote_root = self.skin_dict['path'],
server = self.skin_dict['server'],
user = self.skin_dict.get('user', None),

View File

@@ -651,8 +651,8 @@ class StdTimeSynch(StdService):
# Zero out the time of last synch, and get the time between synchs.
self.last_synch_ts = 0
self.clock_check = int(config_dict['Station'].get('clock_check', 14400))
self.max_drift = int(config_dict['Station'].get('max_drift', 5))
self.clock_check = int(config_dict['StdTimeSynch'].get('clock_check', 14400))
self.max_drift = int(config_dict['StdTimeSynch'].get('max_drift', 5))
self.bind(weewx.STARTUP, self.startup)
self.bind(weewx.PRE_LOOP, self.pre_loop)
@@ -675,12 +675,13 @@ class StdTimeSynch(StdService):
try:
console_time = self.engine.console.getTime()
if console_time is None: return
diff = console_time - now_ts
# getTime can take a long time to run, so we use the current system time
diff = console_time - time.time()
syslog.syslog(syslog.LOG_INFO,
"wxengine: Clock error is %.2f seconds (positive is fast)" % diff)
if abs(now_ts - console_time) > self.max_drift:
if abs(diff) > self.max_drift:
try:
self.engine.console.setTime(now_ts)
self.engine.console.setTime()
except NotImplementedError:
syslog.syslog(syslog.LOG_DEBUG, "wxengine: Station does not support setting the time")
except NotImplementedError:

View File

@@ -6,7 +6,28 @@ weewx change history
Removed the no longer needed serviced StdRESTful, obsolete since V2.6
2.x.x
X.X.X XX/XX/XX
Enabled multiple rsync instances for a single weewx instance.
Added catchup to the WS28xx driver, but still no hardware record generation.
Moved clock synchronization options clock_check and max_drift back to
section [StdTimeSynch].
Changed lux-to-W/m^2 conversion factor in the fine offset driver.
Added rain rate calculation to Ultimeter driver.
Changed setTime to retrieve system time directly rather than using a value
passed by the engine. This greatly improves the accuracy of StdTimeSync,
particularly in network based implementations.
Fixed ENDPOINT_IN in the te923 driver. This should provide better
compatibility with a wider range of pyusb versions.
2.6.4 06/16/14
The WMR100 driver now calculates SLP in software. This fixes a problem
with the WMRS200 station, which does not allow the user to set altitude.
@@ -34,9 +55,9 @@ Prompt for metric/US units for debian installations.
For WS28xx stations, return 0 for battery ok and 1 for battery failure.
If the console has successfully been opened up but then on subsequent opens
suffers an I/O error, weewx will now attempt a retry (before it would just
exit).
If a connection to the console has been successfully opened, but then on
subsequent connection attempts suffers an I/O error, weewx will now attempt
a retry (before it would just exit).
2.6.3 04/10/14

View File

@@ -23,7 +23,7 @@ table#stattypes td {
</a>
<h1 class="title">Customizing weewx<br />
<span class="version">
Version: 3.0.0a1
Version: 2.6.4
</span>
<h1>Table of Contents</h1>
@@ -157,8 +157,9 @@ table#stattypes td {
that it they do not actually generate anything. Instead, they use the
reporting service engine to arrange for things to be transferred to a
remote server. </p>
<h3>Skins</h3>
<p>Each report has a <em>Skin</em> associated with it. For most reports,
<p>Each report has a <em>skin</em> associated with it. For most reports,
the relationship with the skin is an obvious one: it contains the
templates, any auxiliary files such as background GIFs or CSS style
sheets, and a <em>skin configuration file</em>, <span class="code">skin.conf</span>.
@@ -190,12 +191,22 @@ table#stattypes td {
});
</script>
<h3>Templates</h3>
<p>A template is a text file that is processed by
<span class="code">weewx</span> to create a new file. A template may
be used to generate HTML, XML, CSV, javascript, or any other type of
text file. A template typically contains variables that are replaced
by when creating the new file. Templates may also contain programming
logic.</p>
<p>Each template file lives in the skin directory of the skin that uses
it. By convention, a template file ends with the .tmpl extension.</p>
<h3>Generators</h3>
<p>To create their output, skins rely on one or more <em>Generators, </em>code
<p>To create their output, skins rely on one or more <em>Generators</em>
that actually create useful things such as HTML files or plot images.
Generators can also copy files around or FTP/rsync them to remote
locations. The default install of <span class="code">weewx</span> includes
the following generators: </p>
locations. The default install of <span class="code">weewx</span>
includes the following generators: </p>
<table class="indent" summary="Generators included in weewx">
<tbody>
<tr class="first_row">
@@ -314,15 +325,22 @@ table#stattypes td {
changing the template files. The former is generally easier, but
occasionally the latter is necessary. </p>
<h2>Changing options</h2>
<p>Changing an option means either modifying the main configuration file <span
class="code">weewx.conf</span>, or the skin configuration file for the
standard skin that comes with the distribution (nominally, file <span class="symcode">$SKIN_ROOT</span><span
class="code">/Standard/skin.conf</span>). </p>
<p>Changing an option means either modifying the main configuration file
<span class="code">weewx.conf</span>, or the skin configuration file
<span class="code">skin.conf</span>.</p>
<p>Each skin will have a <span class="code">skin.conf</span> that defines
its default configuration. The examples in this guide refer to the
standard skin that comes with the distribution.</p>
<h3>Changing options in <span class="code">skin.conf</span></h3>
<p>With this approach, the user edits the skin configuration file for the
standard skin that comes with <span class="code">weewx</span>, located
in <span class="symcode">$SKIN_ROOT</span><span class="code">/Standard/skin.conf</span>,
using a text editor. For example, suppose you wish to use metric units
<p>With this approach, edit the skin configuration file with a text
editor. Changes made in this way will be used by
<span class="code">weewx</span> the next time it generates reports,
which is typically the next archive interval; there is no need to
restart <span class="code">weewx</span> to see the results of the
changes.</p>
<p>For the standard skin that comes with <span class="code">weewx</span>,
the file is <span class="symcode">$SKIN_ROOT</span><span class="code">/Standard/skin.conf</span>.</p>
<p>For example, suppose you wish to use metric units
in the presentation layer, instead of the default US Customary Units.
The section that controls units is <span class="code">[Units][[Groups]]</span>.
It looks like this: </p>
@@ -382,15 +400,17 @@ table#stattypes td {
...</pre>
<h3>Overriding options in <span class="code">skin.conf</span> from <span
class="code">weewx.conf</span></h3>
<p>This approach is very similar, except that instead of changing the skin
configuration file directly, you override its options by editing the
main configuration file, <span class="code">weewx.conf</span>. The
<p>This approach is very similar, except that instead of changing the
skin configuration file directly, you override its options by editing
the main configuration file, <span class="code">weewx.conf</span>. The
advantage of this approach is that you can use the same skin to produce
several different output, each with separate options. </p>
several different output, each with separate options.</p>
<p>With this approach, you must restart <span class="code">weewx</span>
to see the effects of any changes.</p>
<p>Revisiting our example, suppose you want two reports, one in US
Customary, the other in Metric. The former will go in the directory <span
class="symcode"> $HTML_ROOT</span>, the latter in a directory, <span
class="symcode"> $HTML_ROOT</span><span class="code">/metric</span>.
Customary, the other in Metric. The former will go in the directory
<span class="symcode"> $HTML_ROOT</span>, the latter in a directory,
<span class="symcode"> $HTML_ROOT</span><span class="code">/metric</span>.
If you just simply modify <span class="code">skin.conf</span>, you can
get one, but not both at the same time. Alternatively, you could create
a whole new skin by copying all the files to a new skin directory
@@ -434,13 +454,10 @@ table#stattypes td {
group_speed = meter_per_second
group_speed2 = meter_per_second2
group_temperature = degree_C
[[FTP]]
...
... (as before) </pre>
<p>We have done two things different from the stock reports. First (1), we
have renamed the first report from <span class="code">StandardReport</span> to
<span class="code">USReport</span> for clarity; and (2) we have
</pre>
<p>We have done two things different from the stock reports. First (1),
we have renamed the first report from <span class="code">StandardReport</span> to
<span class="code">USReport</span> for clarity; and second (2), we have
introduced a new report <span class="code">MetricReport</span>, just
like the first, except it puts its results in a different spot and uses
different units. Both use the same skin, the <span class="code">Standard</span>
@@ -607,7 +624,7 @@ or in foobar units: $day.barometer.min.foobar
<td>Comment</td>
</tr>
<tr>
<td class='text_highlight'> <em>(no tag)</em> </td>
<td class='text_highlight'>(no tag)</td>
<td>Value is returned as a string, formatted using an appropriate
string format from <span class="code">skin.conf</span>. A unit
label (e.g., <span class='code'>&deg;F</span>) from <span class="code">skin.conf</span> is also attached
@@ -644,7 +661,7 @@ or in foobar units: $day.barometer.min.foobar
</td>
</tr>
<tr>
<td class="code text_highlight">.nolabel(string_format, NONE_string)</td>
<td class="code text_highlight">.nolabel(<em>string_format, NONE_string</em>)</td>
<td>Value is returned as a string, using the string format specified
with <em>string_format</em>. If the value is <span class="code">None</span>,
the string <span class="code">NONE_string</span> will be
@@ -677,7 +694,7 @@ or in foobar units: $day.barometer.min.foobar
<td>Returned Value</td>
</tr>
<tr>
<td class="first_col"><em>(no tag)</em></td>
<td class="first_col">(no tag)</td>
<td>From <span class="code">skin.conf</span></td>
<td>From <span class="code">skin.conf</span></td>
<td>From <span class="code">skin.conf</span></td>
@@ -843,8 +860,8 @@ or in foobar units: $day.barometer.min.foobar
</table>
<p>Note: </p>
<ul>
<li>Tags that take an argument (such as <span class="code">.string(NONE_string)</span>)
do not require parenthesis if the argument is omitted.Thus, you can
<li>Tags that take an argument, such as <span class="code">.string(NONE_string)</span>,
do not require parenthesis if the argument is omitted. Thus, you can
specify either <span class="code">$month.outTemp.string()</span> or <span
class="code">$month.outTemp.string</span>, if you want the default
value of <span class="code">NONE_string</span>. They produce the same

View File

@@ -89,7 +89,7 @@ sudo apt-get -f install</p>
<h3>Customize</h3>
<p>
To enable uploads such as Weather Underground or to customize reports, modify the configuration file <span class='code'>/etc/weewx.conf</span>. See the <a href="usersguide.htm">User Guide</a> and <a href="customizing.htm">Customization Guide</a> for details.
To enable uploads such as Weather Underground or to customize reports, modify the configuration file <span class='code'>/etc/weewx/weewx.conf</span>. See the <a href="usersguide.htm">User Guide</a> and <a href="customizing.htm">Customization Guide</a> for details.
</p>
<p>
<span class='code'>weewx</span> must be restarted for configuration

View File

@@ -123,7 +123,7 @@
<h3>Customize</h3>
<p>
To enable uploads such as Weather Underground or to customize reports, modify the configuration file <span class='code'>/etc/weewx.conf</span>. See the <a href="usersguide.htm">User Guide</a> and <a href="customizing.htm">Customization Guide</a> for details.
To enable uploads such as Weather Underground or to customize reports, modify the configuration file <span class='code'>/etc/weewx/weewx.conf</span>. See the <a href="usersguide.htm">User Guide</a> and <a href="customizing.htm">Customization Guide</a> for details.
</p>
<p>
<span class='code'>weewx</span> must be restarted for configuration file

View File

@@ -230,9 +230,9 @@ function showstartup(id) {
</p>
<h3>Run</h3>
<p>Run the main program from the command line:</p>
<p>Run the main program directly:</p>
<p class="tty">cd /home/weewx
./bin/weewxd weewx.conf</p>
sudo ./bin/weewxd weewx.conf</p>
<p>Or as a daemon automatically when the computer starts:</p>
<div class='tabs'>
<div id='startup-tab-debian' class='tab selected' onclick="showstartup('debian')">Debian <img src='logo-debian.png' class='thumbnail' /> <img src='logo-ubuntu.png' class='thumbnail' /> <img src='logo-mint.png' class='thumbnail' /></div>
@@ -281,7 +281,7 @@ function showstartup(id) {
<h3>Customize</h3>
<p>
To enable uploads such as Weather Underground or to customize reports, modify the configuration file <span class='code'>/etc/weewx.conf</span>. See the <a href="usersguide.htm">User Guide</a> and <a href="customizing.htm">Customization Guide</a> for details.
To enable uploads such as Weather Underground or to customize reports, modify the configuration file <span class='code'>/home/weewx/weewx.conf</span>. See the <a href="usersguide.htm">User Guide</a> and <a href="customizing.htm">Customization Guide</a> for details.
</p>
<p>
<span class='code'>weewx</span> must be restarted for configuration file

View File

@@ -121,7 +121,7 @@
<h3>Customize</h3>
<p>
To enable uploads such as Weather Underground or to customize reports, modify the configuration file <span class='code'>/etc/weewx.conf</span>. See the <a href="usersguide.htm">User Guide</a> and <a href="customizing.htm">Customization Guide</a> for details.
To enable uploads such as Weather Underground or to customize reports, modify the configuration file <span class='code'>/etc/weewx/weewx.conf</span>. See the <a href="usersguide.htm">User Guide</a> and <a href="customizing.htm">Customization Guide</a> for details.
</p>
<p>
<span class='code'>weewx</span> must be restarted for configuration file

View File

@@ -15,7 +15,7 @@
</a>
<h1 class="title">Upgrading <span class="code">weewx</span><br/>
<span class='version'>
Version: 3.0.0a1
Version: 2.6.4
</span>
</h1>

View File

@@ -33,7 +33,7 @@ function showtab(tab,id) {
</a>
<h1 class="title">User's Guide to the weewx Weather System<br />
<span class='version'>
Version: 3.0.0a1
Version: 2.6.4
</span>
</h1>
@@ -342,7 +342,7 @@ Version: 3.0.0a1
<tr>
<td>WS-23XX</td>
<td>Serial</td>
<td class="code">pyserial</td>
<td class="code">fcntl/select</td>
<td>WS23xx<sup><a href='#ws23xx'>6</a></sup></td>
<td>Experimental</td>
</tr>
@@ -554,23 +554,23 @@ Version: 3.0.0a1
<tr>
<td class="text_highlight" rowspan='2'>TechnoLine</td>
<td>WS-2300</td>
<td>USB</td>
<td class="code">pyserial</td>
<td>Serial</td>
<td class="code">fcntl/select</td>
<td>WS23xx<sup><a href='#ws23xx'>6</a></sup></td>
<td>Experimental</td>
</tr>
<tr>
<td>WS-2350</td>
<td>USB</td>
<td class="code">pyserial</td>
<td>Serial</td>
<td class="code">fcntl/select</td>
<td>WS23xx<sup><a href='#ws23xx'>6</a></sup></td>
<td>Experimental</td>
</tr>
<tr>
<td class="text_highlight" rowspan='5'>TFA</td>
<td>Matrix</td>
<td>USB</td>
<td class="code">pyserial</td>
<td>Serial</td>
<td class="code">fcntl/select</td>
<td>WS23xx<sup><a href='#ws23xx'>6</a></sup></td>
<td>Experimental</td>
</tr>
@@ -1640,7 +1640,7 @@ longitude = -77.0366</pre>
It uses the skin &quot;<span class="code">Standard</span>&quot;, which generates
four HTML pages (&quot;day&quot;, &quot;week&quot;, &quot;month&quot;, and &quot;year&quot;
observations), plot graphs for same, an RSS feed, and NOAA monthly and yearly
reports. Unless changed otherwise, it uses US Customary Units and puts the results
reports. The default configuration uses US Customary Units and puts the results
in <span class="code">public_html</span> and subdirectory <span class="code">
public_html/NOAA</span>. </p>
<h3 class="config_section">[[FTP]]</h3>
@@ -1701,27 +1701,38 @@ longitude = -77.0366</pre>
on the remote server. Valid values are 1 to enable and 0 to disable. Required.
Default is 0.</p>
<h2 class="config_section" id="StdConvert">[StdConvert]</h2>
<p>This section is for configuring the <span class="code">StdConvert</span>
service. This service acts as a filter, converting the unit system coming off
your hardware to a target output unit system. Everything that follows, including
the archiving service, will use the target unit system. Hence, your data
will be stored using your chosen unit system. </p>
<p><em>Once chosen, it cannot be changed!</em> Weewx does not allow you to mix
unit systems within the databases. You must chose one or the other and then
stick with it. This means that users coming from wview (which uses US Customary)
should not change the default setting. Having said this, there is a way of reconfiguring
the database to use another unit system. See the section
<p>This section is for configuring the <span class="code">StdConvert</span>
service.</p>
<p class='note'><strong>Note!</strong><br/>
If you would like to change the units that are displayed
in plots or files, you should make changes to the skin as described in
the <a href="customizing.htm">Customizing Guide</a>, under section
<em><a href="customizing.htm#Changing_options">Changing options</a></em>.
</p>
<p>The <span class="code">StdConvert</span> service acts as a filter,
converting the unit system coming off your hardware to a target output
unit system. Everything that follows, including the archiving service,
will use the target unit system. Hence, your data will be stored using
your chosen unit system. </p>
<p><em>Once chosen, it cannot be changed!</em> Weewx does not allow you to
mix unit systems within the databases. You must chose one or the other
and then stick with it. This means that users coming from wview (which
uses US Customary) should not change the default setting. Having said
this, there is a way of reconfiguring the database to use another unit
system. See the section
<a href="customizing.htm#Changing_the_unit_system">Changing the unit system</a>
in the Customizing Guide.</p>
<p>Note that whatever you choose here, it does not affect your options for the
unit system to be used for <i>reporting</i>. Because of this, unless you
have a special purpose application, there is really no good reason to change
from the default, which is <span class="code">US</span>. </p>
<p class="warning"><strong>Warning!</strong><br />
If, despite these precautions, you do
decide to change to Metric, be sure to read the sections <span class="code">
<a href="#StdCalibrate">[StdCalibrate]</a></span> and <span class="code">
<a href="#StdQC">[StdQC]</a></span> below, and change the units there as well!</p>
<p>Note that whatever you choose here, it does not affect your options for
the unit system to be used for <i>reporting</i>. Because of this, unless
you have a special purpose application, there is really no good reason to
change from the default, which is <span class="code">US</span>. </p>
<p class="warning"><strong>Warning!</strong><br />
If, despite these precautions, you do decide to change the units of data
stored in the database, be sure to read the sections
<span class="code"><a href="#StdCalibrate">[StdCalibrate]</a></span> and
<span class="code"><a href="#StdQC">[StdQC]</a></span>, and change the
units there as well!</p>
<p class="config_option">target_unit</p>
<p>Set to either <span class="code">US</span>, <span class="code">METRICWX</span>,
or <span class="code">METRIC</span>. The difference between
@@ -2003,7 +2014,7 @@ report_services = weewx.wxengine.StdPrint, weewx.wxengine.StdReport
configuration utilities supplied with weewx. Directions follow for</p>
<ul>
<li><a href="#wee_config_vantage">Davis Vantage stations</a></li>
<li><a href="#wee_config_fousb">Fine Offset stations</a></li>
<li><a href="#wee_config_fousb">Fine Offset 10xx, 20xx, and 30xx stations</a></li>
<li><a href="#wee_config_ws23xx">La Crosse WS23xx stations</a></li>
<li><a href="#wee_config_ws28xx">La Crosse WS28xx stations</a></li>
<li><a href="#wee_config_cc3000">RainWise CC3000 data logger</a></li>
@@ -2161,7 +2172,7 @@ Davis Vantage EEPROM settings:
Because the command dumps <em>all</em> data, it may result in many
duplicate primary key errors. These can be ignored.</p>
<h2 id="wee_config_fousb">Fine Offset</h2>
<h2 id="wee_config_fousb">Fine Offset 10xx, 20xx, 30xx</h2>
<p>The configuration utility <span class='code'>wee_config_fousb</span> is
designed to diagnose and configure Fine Offset stations.</p>
<p>Run it with <span class='code'>--help</span> as an option to see its usage:</p>
@@ -2536,7 +2547,7 @@ Mutating actions will request confirmation before proceeding.
option.</p>
<pre class="tty"><span class="symcode">$BIN_ROOT</span>/wee_config_cc3000 --info </pre>
<p>This will result in something like this:</p>
<pre class='tty'>firmware: Rainwise CC-3000 Version: 1.3 Build 002 Jun 05 2013
<pre class='tty'>firmware: Rainwise CC-3000 Version: 2.6.4
time: 2014/06/02 08:22:17
units: ENGLISH
memory: 251372 bytes, 4334 records, 12%
@@ -2590,14 +2601,13 @@ mysql&gt; GRANT select, update, create, delete, insert ON stats.* TO weewx@local
[StdArchive]</a></span> for details.</p>
<h1 id="running">Running <span class="code">weewx</span></h1>
<p><span class="code">Weewx</span> can be run either from the command line
(useful for diagnostic purposes because it will print out a summary of
every LOOP data), or as a daemon. When first trying
<span class="code">weewx</span>, it is best to run it from the command
line because you will be able to see command line diagnostics, as well
<p><span class="code">Weewx</span> can be run either directly,
or as a daemon. When first trying
<span class="code">weewx</span>, it is best to run it directly
because you will be able to see sensor output and diagnostics, as well
as log messages. Once everything is working properly, run it as a
daemon.</p>
<h2>Running from the command line</h2>
<h2>Running directly</h2>
<p>To run <span class="code">weewx</span> directly, invoke
the main program, <span class="code">weewxd</span>, giving
the configuration file as its only parameter: </p>
@@ -2610,7 +2620,8 @@ mysql&gt; GRANT select, update, create, delete, insert ON stats.* TO weewx@local
<p><span class="code">Weewx</span> will then start monitoring live sensor
data (also referrred to as 'LOOP' data),
printing a short version of the received data on standard output, about
once every two seconds. </p>
once every two seconds for a Vantage station, or considerably longer
for some other stations. </p>
<p>You can tell a running instance of <span class="code">weewx</span> to
reread its configuration file by sending it the
<span class="code">HUP</span> signal.
@@ -2821,21 +2832,27 @@ sudo /etc/init.d/apache2 restart</p>
<span class='code'>weewx</span>.
</p>
<p>
<strong>Configuration.</strong>
It is not necessary to backup the images and HTML files generated from
templates, since weewx will easily create those again. This includes
the NOAA reports in some skins.
</p>
<h2>Configuration</h2>
<p>
Save the <span class='code'>weewx.conf</span> file.
</p>
<table class="locations" style="width:70%">
<tr>
<td style="width: 30%">setup.py</td>
<td style="width: 30%">setup.py:</td>
<td class='tty'>/home/weewx/weewx.conf</td>
</tr>
<tr>
<td >DEB/RPM</td>
<td >DEB/RPM:</td>
<td class='tty'>/etc/weewx/weewx.conf</td>
</tr>
</table>
<h2>Weather data</h2>
<p>
<strong>Weather data.</strong> Meteorological ata are saved in the
Meteorological data are saved in the
archive database. For a Sqlite
configuration, simply save the <span class='code'>weewx.sdb</span>
file. For a MySQL configuration, save a dump of the archive database.
@@ -2844,49 +2861,48 @@ sudo /etc/init.d/apache2 restart</p>
</p>
<table class="locations" style="width:70%">
<tr>
<td style="width: 30%">setup.py</td>
<td style="width: 30%">setup.py:</td>
<td class='tty'>/home/weewx/archive/weewx.sdb</td>
</tr>
<tr>
<td >DEB/RPM</td>
<td >DEB/RPM:</td>
<td class='tty'>/var/lib/weewx/weewx.sdb</td>
</tr>
</table>
<h2>Skins and templates</h2>
<p>
<strong>Skins and templates.</strong>
Save the contents of the skins directory.
Save the contents of the skins directory if you have modified the default
skin or if you have added any new skins or template files.
</p>
<table class="locations" style="width:70%">
<tr>
<td style="width: 30%">setup.py</td>
<td style="width: 30%">setup.py:</td>
<td class='tty'>/home/weewx/skins</td>
</tr>
<tr>
<td >DEB/RPM</td>
<td >DEB/RPM:</td>
<td class='tty'>/etc/weewx/skins</td>
</tr>
</table>
<h2>Other customizations</h2>
<p>
<strong>Other customizations.</strong> Save the contents of the
Save the contents of the
<span class='code'>user</span> directory if you have modified the
database schema or added any extensions. If the extensions save data
to a database you should backup those databases as well.
</p>
<table class="locations" style="width:70%">
<tr>
<td style="width: 30%">setup.py</td>
<td style="width: 30%">setup.py:</td>
<td class='tty'>/home/weewx/bin/user</td>
</tr>
<tr>
<td >DEB/RPM</td>
<td >DEB/RPM:</td>
<td class='tty'>/usr/share/weewx/user</td>
</tr>
</table>
<p>
It is not necessary to backup the images and HTML files generated from
templates, since weewx will easily create those again. This includes
the NOAA reports in some skins.
</p>
<h2>Restoring from backup</h2>
<p>
To restore from backup, do a fresh install of
<span class='code'>weewx</span> then replace the default files with
@@ -2907,13 +2923,13 @@ sudo /etc/init.d/apache2 restart</p>
<li style="margin-bottom:1em"><a href="#monitoring">Look at the log file</a>. I am always
happy to take questions, but the first thing I will ask you is,
&quot;Did you look at the log file?&quot;
<p class='tty' style="margin-top:1em">tail -f /var/log/messages</p>
<p class='tty' style="margin-top:1em">sudo tail -f /var/log/syslog</p>
</li>
<li style="margin-bottom:1em">Run from the command line. Generally, <span class="code">weewx</span>
will catch and log any unrecoverable exceptions. But if you are getting
strange results, it is worth running from the command line and looking
for any clues.
<p class='tty' style="margin-top:1em"><span class="symcode">$BIN_ROOT</span>/weewxd <span class="symcode">$CONFIG_ROOT</span>/weewx.conf</p>
<li style="margin-bottom:1em">Run directly rather than as a daemon.
Generally, <span class="code">weewx</span> will catch and log any
unrecoverable exceptions. But if you are getting strange results,
it is worth running directly and looking for any clues.
<p class='tty' style="margin-top:1em">sudo <span class="symcode">$BIN_ROOT</span>/weewxd <span class="symcode">$CONFIG_ROOT</span>/weewx.conf</p>
</li>
</ul>
@@ -3183,7 +3199,8 @@ Jan 1 09:46:32 saga weewx[15292]: wxengine: pid file is /var/run/weewx.pid</pre
<h3><span class="code">configobj</span> errors</h3>
<p>These are errors in the configuration file. Two are very common.
Incidentally, these errors are far easier to diagnose when
<span class="code">weewx</span> is run from the command line. </p>
<span class="code">weewx</span> is run directly than when it is run
as a daemon. </p>
<h4><span class="code">configobj.DuplicateError</span> exception</h4>
<p>This error is caused by using an identifier more than once in the
configuration file. For example, you may have inadvertently listed
@@ -3558,8 +3575,8 @@ port = /dev/cuaU0</pre>
rate of V3.X this is unlikely to happen anytime soon. In any case, I doubt the
transition will affect the average <span class="code">weewx</span> user. </p>
<p>All writes to the databases are protected by transactions. You can kill the
program at any time (either Control-C if run from the command line or &quot;<span class="code">/etc/init.d/weewx
stop</span>&quot; if a daemon) without fear of corrupting the databases. </p>
program at any time (either Control-C if run directly or &quot;<span class="code">/etc/init.d/weewx
stop</span>&quot; if run as a daemon) without fear of corrupting the databases. </p>
<p>The code makes ample use of exceptions to insure graceful recovery from problems
such as network outages. It also monitors socket and console timeouts, restarting
whatever it was working on several times before giving up. In the case of an
@@ -3690,7 +3707,9 @@ port = /dev/cuaU0</pre>
stations use an odd mix of US and metric. The Fine Offset
stations are metric. The LaCrosse stations are metric. The
Hideki stations are a mix of US and metric. One-wire devices
can be either US or metric.</li>
can be either US or metric. RainWise data loggers can be configured
to use either US or metric. PeetBros devices use a mix of US and
metric.</li>
<li>In the database. Either US or Metric can be used.</li>
<li>In the presentation (i.e., html and image files). </li>
</ol>

View File

@@ -1,3 +1,6 @@
* Mon Jun 16 2014 Matthew Wall (weewx) <mwall@users.sourceforge.net> - 2.6.4-1
- new upstream release
- added cc3000, ultimeter, ws1 drivers
* Thu Apr 10 2014 Matthew Wall (weewx) <mwall@users.sourceforge.net> - 2.6.3-1
- new upstream release
* Sun Feb 16 2014 Matthew Wall (weewx) <mwall@users.sourceforge.net> - 2.6.2-1

View File

@@ -1,3 +1,8 @@
weewx (2.6.4-1) unstable; urgency=low
* new upstream release
* added cc3000, ultimeter, ws1 drivers
* added option to specify display units during installation
-- Matthew Wall (weewx) <mwall@users.sourceforge.net> Mon, 16 Jun 2014 07:22:26 -0400
weewx (2.6.3-1) unstable; urgency=low
* new upstream release
-- Matthew Wall (weewx) <mwall@users.sourceforge.net> Thu, 10 Apr 2014 20:25:10 -0400

View File

@@ -1,26 +1,12 @@
############################################################################################
# #
# #
# FTP CONFIGURATION FILE #
# #
# #
############################################################################################
# #
# Copyright (c) 2010 Tom Keffer <tkeffer@gmail.com> #
# #
# See the file LICENSE.txt for your full rights. #
# #
############################################################################################
#
# $Revision$
# $Author$
# $Date$
#
############################################################################################
# This isn't really a "report". Instead, we use the report engine to run an FTP service.
###############################################################################
# $Id$
# Copyright (c) 2010 Tom Keffer <tkeffer@gmail.com> #
# #
# FTP CONFIGURATION FILE #
# This 'report' does not generate any files. Instead, we use the report #
# engine to invoke FTP, which copies files to another location. #
###############################################################################
[Generators]
# The list of generators that are part of this report:
generator_list = weewx.reportengine.FtpGenerator
generator_list = weewx.reportengine.FtpGenerator

View File

@@ -1,27 +1,13 @@
############################################################################################
# #
# #
# RSYNC CONFIGURATION FILE #
# #
# #
############################################################################################
# #
# Copyright (c) 2012 Will Page <compenguy@gmail.com> #
# With credit to Tom Keffer <tkeffer@gmail.com> #
# #
# See the file LICENSE.txt for your full rights. #
# #
############################################################################################
#
# $Revision$
# $Author$
# $Date$
#
############################################################################################
# This isn't really a "report". Instead, we use the report engine to run an rsync service.
[Generators]
# The list of generators that are part of this report:
generator_list = weewx.reportengine.RsyncGenerator
###############################################################################
# $Id$
# Copyright (c) 2012 Will Page <compenguy@gmail.com> #
# With credit to Tom Keffer <tkeffer@gmail.com> #
# #
# RSYNC CONFIGURATION FILE #
# This 'report' does not generate any files. Instead, we use the report #
# engine to invoke rsync, which synchronizes files between two locations. #
###############################################################################
[Generators]
generator_list = weewx.reportengine.RsyncGenerator

View File

@@ -283,9 +283,14 @@
#if $Extras.has_key('radar_img')
<div id="radar_img">
#if $Extras.has_key('radar_url')
<a href="$Extras.radar_url">
<img src="$Extras.radar_img" alt="Radar" /></a>
#end if
<img src="$Extras.radar_img" alt="Radar" />
#if $Extras.has_key('radar_url')
</a>
<p>Click image for expanded radar loop</p>
#end if
</div>
#end if

View File

@@ -73,11 +73,18 @@
</table>
</div>
#if $Extras.has_key('radar_url')
<!-- yes I was too lazy to CSS the style below :-) -->
#if $Extras.has_key('radar_img')
<div class="radar">
<a href="$Extras.radar_url"><img src="$Extras.radar_url"></img></a>
<p style="font-size: 12px; color: black; text-align: center;"> $current.dateTime</p>
#if $Extras.has_key('radar_url')
<a href="$Extras.radar_url">
#end if
<img src="$Extras.radar_img" alt="Radar" />
#if $Extras.has_key('radar_url')
</a>
#end if
<!-- yes I was too lazy to CSS the style below :-) -->
<p style="font-size: 12px; color: black; text-align: center;"> $current.dateTime</p>
</div>
#end if

View File

@@ -1,21 +1,7 @@
###############################################################################
# #
# #
# STANDARD SKIN CONFIGURATION FILE #
# #
# #
###############################################################################
# #
# $Id$
# Copyright (c) 2010 Tom Keffer <tkeffer@gmail.com> #
# #
# See the file LICENSE.txt for your full rights. #
# #
###############################################################################
#
# $Revision$
# $Author$
# $Date$
#
# STANDARD SKIN CONFIGURATION FILE #
###############################################################################
[Extras]

View File

@@ -9,7 +9,8 @@
create 644 syslog adm
sharedscripts
postrotate
reload rsyslog > /dev/null 2>&1
service rsyslog restart > /dev/null
# reload rsyslog > /dev/null 2>&1
# /etc/init.d/rsyslog stop
# /etc/init.d/rsyslog start
endscript

View File

@@ -285,7 +285,7 @@ while(defined($_ = <STDIN>)) {
/ws28xx: MainThread: frequency is/ ||
/ws28xx: MainThread: altitude is/ ||
/ws28xx: MainThread: pressure offset is/ ||
/ws28xx: MainThread: found transceiver on USB/ ||
/ws28xx: MainThread: found transceiver/ ||
/ws28xx: MainThread: manufacturer: LA CROSSE TECHNOLOGY/ ||
/ws28xx: MainThread: product: Weather Direct Light Wireless/ ||
/ws28xx: MainThread: interface/ ||
@@ -311,6 +311,9 @@ while(defined($_ = <STDIN>)) {
/ws28xx: MainThread: release USB interface/ ||
/ws28xx: MainThread: claiming USB interface/ ||
/ws28xx: MainThread: CCommunicationService.init/ ||
/ws28xx: MainThread: Scanning historical records/ ||
/ws28xx: MainThread: Scanned/ ||
/ws28xx: MainThread: Found/ ||
/ws28xx: RFComm: console is paired to device/ ||
/ws28xx: RFComm: starting rf communication/ ||
/ws28xx: RFComm: stopping rf communication/ ||
@@ -399,6 +402,7 @@ while(defined($_ = <STDIN>)) {
/owfs: polling interval is / ||
/owfs: sensor map is / ||
/cmon: cpuinfo: / ||
/cmon: sysinfo: / ||
/cmon: Skipping record/ ||
/forecast: .* starting thread/ ||
/forecast: .* terminating thread/ ||