mirror of
https://github.com/weewx/weewx.git
synced 2026-06-09 17:45:24 -04:00
Catch up with main trunk.
This commit is contained in:
5
MANIFEST
5
MANIFEST
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__" :
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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),
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'>°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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 "<span class="code">Standard</span>", which generates
|
||||
four HTML pages ("day", "week", "month", and "year"
|
||||
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> 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> 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,
|
||||
"Did you look at the log file?"
|
||||
<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 "<span class="code">/etc/init.d/weewx
|
||||
stop</span>" if a daemon) without fear of corrupting the databases. </p>
|
||||
program at any time (either Control-C if run directly or "<span class="code">/etc/init.d/weewx
|
||||
stop</span>" 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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/ ||
|
||||
|
||||
Reference in New Issue
Block a user