Bill,
Try the attached weewxwd3.py, it's v1.04 (whereas you had v1.03) but should
be fully backward compatible. To install:
1. rename your existing weewxwd3.py:
$ mv /usr/share/weewx/user/weewxwd3.py mv /usr/share/weewx/user/
weewxwd3_1_03.py
2. download the attached weewxwd3.py and save it in directory
/usr/share/weewx/user
3. restart WeeWX.
Monitor the log, hopefully that will fix the error that is causing WeeWX to
exit.
Gary
On Friday, 7 September 2018 10:50:03 UTC+10, Bill M wrote:
>
> And hers's the error log from the last attempt to start!
>
> I'm off to bed shortly so will take another look tomorrow!
>
> Bill
>
> On Thursday, September 6, 2018 at 7:37:51 PM UTC-5, Bill M wrote:
>>
>> Tryed it but no joy
>>
>> my changed weewswd3.py attached, in case I did the changes wrong!
>>
>> On Thursday, September 6, 2018 at 6:25:12 PM UTC-5, gjr80 wrote:
>>>
>>> Ok, you have an old version of weewxwd3.py that is, how shall I say, not
>>> quite as robust as it should be. The quick fix is to add a line that will
>>> avoid the missing windSpeed error. If you are up for it:
>>>
>>> 1. edit /usr/share/weewx/user/weewxwd3.py
>>> 2. go to about line 172, you should see code like this:
>>>
>>> # has weewx already calculated appTemp?
>>> if 'appTemp' not in data_metricwx:
>>> # no, so calculate it ourself and add to our WD data
>>> wd_data['appTemp'] =
>>> weewx.wxformulas.apptempC(data_metricwx['outTemp'],
>>>
>>> data_metricwx['outHumidity'],
>>>
>>> data_metricwx['windSpeed'])
>>>
>>> You need to add an additional line so it looks like:
>>>
>>> # has weewx already calculated appTemp?
>>> if 'appTemp' not in data_metricwx:
>>> # no, so calculate it ourself and add to our WD data
>>> if 'outTemp' in data_metricwx and 'outHumidity' in
>>> data_metricwx and 'windSpeed' in data_metricwx:
>>> wd_data['appTemp'] =
>>> weewx.wxformulas.apptempC(data_metricwx['outTemp'],
>>>
>>> data_metricwx['outHumidity'],
>>>
>>> data_metricwx['windSpeed'])
>>>
>>> 3. Be careful with indenting, use the space bar not the tab key, python
>>> is particular with indents. Indents are multiple of 4 spaces, unfortunately
>>> posting this on the iPad makes it difficult to format the above code in a
>>> mono space font so the indents probably look at bit dodgy.
>>> 4. Save weewxwd3.py
>>> 5. Restart WeeWX
>>>
>>> Have a look at the log and check that WeeWX is running without error.
>>>
>>> Gary
>>>
>>> PS. Just saw your post about taking my time. I guess if you do want to
>>> reimage your machine go ahead, you should not lose data provided you have a
>>> logger with memory connected to your station. Depending on archive interval
>>> you should have a good 6 days or more at a 5 minute archive interval. WeeWX
>>> will just pick up any missing data when it next starts. Irrespective of
>>> whether you reimage or not we should get you onto the latest WeeWX-WD
>>> version, it's a bit more robust than the version you are using.
>>>
>>>
--
You received this message because you are subscribed to the Google Groups
"weewx-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# Version: 1.0.4 Date: 20 July 2018
#
# Revision History
# 20 July 2018
# - fixed bug that occurred on partial packet stations that occasionally
# omit outTemp from packets/records
# - changed behaviour for calculating derived obs. If any one of the
# pre-requisite obs are missing then the derived obs is not calculated
# and not added to the packet/record. If all of the pre-requisite obs
# exist but one or more is None then the derived obs is set to None. If
# all pre-requisite obs exist and are non-None then the derived obs is
# calculated and added to the packet/record as normal.
# - simplified WdArchive new_archive_record() method
# 31 March 2017 v1.0.3
# - no change, version number change only
# 14 December 2016 v1.0.2
# - no change, version number change only
# 30 November 2016 v1.0.1
# - now uses humidex and appTemp formulae from weewx.wxformulas
# - weewx-WD db management functions moved to wd_database utility
# - implemented syslog wrapper functions
# - minor reformatting
# - replaced calls to superseded DBBinder.get_database method with
# DBBinder.get_manager method
# - removed database management utility functions and placed in new
# wd_database utility
# 10 January 2015 v1.0.0
# - rewritten for Weewx v3.0
# - uses separate database for weewx-WD specific data, no longer
# recycles existing weewx database fields
# - added __main__ to allow command line execution of a number of db
# management actions
# - removed --debug option from main()
# - added --create_archive option to main() to create the weewxwd
# database
# - split --backfill_daily into separate --drop_daily and
# --backfill_daily options
# - added 'user.' to all weewx-WD imports
# 18 September 2014 v0.9.4 (never relaeased)
# - added GNU license text
# 18 May 2014 v0.9.2
# - removed code that set windDir/windGustDir to 0 if windDir/windGustDir
# were None respectively
# 30 July 2013 v0.9.1
# - revised version number to align with weewx-WD version numbering
# 20 July 2013 v0.1
# - initial implementation
#
import syslog
import weewx
import time
import weewx.engine
import weewx.wxformulas
import weewx.units
from datetime import datetime
from weewx.units import obs_group_dict
WEEWXWD_VERSION = '1.0.4'
schema = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
('usUnits', 'INTEGER NOT NULL'),
('interval', 'INTEGER NOT NULL'),
('humidex', 'REAL'),
('appTemp', 'REAL'),
('outTempDay', 'REAL'),
('outTempNight', 'REAL')]
def logmsg(level, src, msg):
syslog.syslog(level, '%s %s' % (src, msg))
def logdbg(src, msg):
logmsg(syslog.LOG_DEBUG, src, msg)
def logdbg2(src, msg):
if weewx.debug >= 2:
logmsg(syslog.LOG_DEBUG, src, msg)
def loginf(src, msg):
logmsg(syslog.LOG_INFO, src, msg)
def logerr(src, msg):
logmsg(syslog.LOG_ERR, src, msg)
def calc_daynighttemps(data):
""" 'Calculate' value for outTempDay.
outTempDay and outTempNight are used to determine warmest night
and coldest day stats. This is done by using two derived
observations; outTempDay and outTempNight. These observations
are defined as follows:
outTempDay: equals outTemp if time of day is > 06:00 and <= 18:00
otherwise it is None
outTempNight: equals outTemp if time of day is > 18:00 or <= 06:00
otherwise it is None
By adding these derived obs to the schema and loop packet the daily
summaries for these obs are populated and aggregate stats can be
accessed as per normal (eg $month.outTempDay.minmax to give the
coldest max daytime temp in the month). Note that any aggregates that
rely on the number of records (eg avg) will be meaningless due to
the way outTempxxxx is calculated.
"""
if data['outTemp'] is not None:
# check if record covers daytime (6AM to 6PM) and if so add
# 'outTemp' to 'outTempDay' remember record timestamped 6AM belongs
# in the night time
if datetime.fromtimestamp(data['dateTime']-1).hour < 6 or datetime.fromtimestamp(data['dateTime']-1).hour > 17:
# ie the data packet is from before 6am or after 6pm
return (None, data['outTemp'])
else:
# ie the data packet is from after 6am and before or including
# 6pm
return (data['outTemp'], None)
else:
return (None, None)
#=============================================================================
# Class WdWXCalculate
#=============================================================================
class WdWXCalculate(weewx.engine.StdService):
def __init__(self, engine, config_dict):
super(WdWXCalculate, self).__init__(engine, config_dict)
# bind ourself to both loop and archive events
self.bind(weewx.NEW_LOOP_PACKET, self.new_loop_packet)
self.bind(weewx.NEW_ARCHIVE_RECORD, self.new_archive_record)
def new_loop_packet(self, event):
# get the packet as METRICWX units (makes the calcs easier)
data_metricwx = weewx.units.to_METRICWX(event.packet)
# start to build our WD data
wd_data = {'usUnits': data_metricwx['usUnits']}
# has weewx already calculated humidex?
if 'humidex' not in data_metricwx:
# no, so calculate it ourself and add to our WD data
if 'outTemp' in data_metricwx and 'outHumidity' in data_metricwx:
wd_data['humidex'] = weewx.wxformulas.humidexC(data_metricwx['outTemp'],
data_metricwx['outHumidity'])
# has weewx already calculated appTemp?
if 'appTemp' not in data_metricwx:
# no, so calculate it ourself and add to our WD data
if 'outTemp' in data_metricwx and 'outHumidity' in data_metricwx and 'windSpeed' in data_metricwx:
wd_data['appTemp'] = weewx.wxformulas.apptempC(data_metricwx['outTemp'],
data_metricwx['outHumidity'],
data_metricwx['windSpeed'])
# if we have outTemp data 'calculate' our day and night outTemp values
# and add to our WD data
if 'outTemp' in data_metricwx:
wd_data['outTempDay'], wd_data['outTempNight'] = calc_daynighttemps(data_metricwx)
# convert our WD data back to the original packet units
wd_data_x = weewx.units.to_std_system(wd_data, event.packet['usUnits'])
# add the WD data to the packet
event.packet.update(wd_data_x)
def new_archive_record(self, event):
# get the packet as METRICWX units (makes the calcs easier)
data_metricwx = weewx.units.to_METRICWX(event.record)
# start to build our WD data
wd_data = {'usUnits': data_metricwx['usUnits']}
# has weewx already calculated humidex?
if 'humidex' not in data_metricwx:
# no, so calculate it ourself and add to our WD data
if 'outTemp' in data_metricwx and 'outHumidity' in data_metricwx:
wd_data['humidex'] = weewx.wxformulas.humidexC(data_metricwx['outTemp'],
data_metricwx['outHumidity'])
# has weewx already calculated appTemp?
if 'appTemp' not in data_metricwx:
# no, so calculate it ourself and add to our WD data
if 'outTemp' in data_metricwx and 'outHumidity' in data_metricwx and 'windSpeed' in data_metricwx:
wd_data['appTemp'] = weewx.wxformulas.apptempC(data_metricwx['outTemp'],
data_metricwx['outHumidity'],
data_metricwx['windSpeed'])
# if we have outTemp data 'calculate' our day and night outTemp values
# and add to our WD data
if 'outTemp' in data_metricwx:
wd_data['outTempDay'], wd_data['outTempNight'] = calc_daynighttemps(data_metricwx)
# convert our WD data back to the original record units
wd_data_x = weewx.units.to_std_system(wd_data, event.record['usUnits'])
# add the WD data to the record
event.record.update(wd_data_x)
#=============================================================================
# Class WdArchive
#=============================================================================
class WdArchive(weewx.engine.StdService):
""" Service to store weewx-WD specific archive data. """
def __init__(self, engine, config_dict):
super(WdArchive, self).__init__(engine, config_dict)
# Extract our binding from the weewx-WD section of the config file. If
# it's missing, fill with a default
if 'WeewxWD' in config_dict:
self.data_binding = config_dict['WeewxWD'].get('data_binding',
'wd_binding')
else:
self.data_binding = 'wd_binding'
# Extract the Weewx binding for use when we check the need for backfill
# from the Weewx archive
if 'StdArchive' in config_dict:
self.data_binding_wx = config_dict['StdArchive'].get('data_binding',
'wx_binding')
else:
self.data_binding_wx = 'wx_binding'
loginf("WdArchive:", "WdArchive will use data binding %s" % self.data_binding)
# setup our database if needed
self.setup_database(config_dict)
# set the unit groups for our obs
obs_group_dict["humidex"] = "group_temperature"
obs_group_dict["appTemp"] = "group_temperature"
obs_group_dict["outTempDay"] = "group_temperature"
obs_group_dict["outTempNight"] = "group_temperature"
# bind ourselves to NEW_ARCHIVE_RECORD event
self.bind(weewx.NEW_ARCHIVE_RECORD, self.new_archive_record)
def new_archive_record(self, event):
"""Called when a new archive record has arrived.
Save WeeWX-WD specific data in the WeeWX-WD archive.
"""
# Put the record in the archive
dbmanager = self.engine.db_binder.get_manager(self.data_binding)
dbmanager.addRecord(event.record)
def setup_database(self, config_dict):
"""Setup the main database archive"""
# This will create the database if it doesn't exist, then return an
# opened instance of the database manager.
dbmanager = self.engine.db_binder.get_manager(self.data_binding, initialize=True)
loginf("WdArchive:", "Using binding '%s' to database '%s'" % (self.data_binding,
dbmanager.database_name))
# Check if we have any historical data to suck in from Weewx main
# archive get a dbmanager for the Weewx archive
dbmanager_wx = self.engine.db_binder.get_manager(self.data_binding_wx,
initialize=False)
# Back fill the daily summaries.
loginf("WdArchive:", "Starting backfill of daily summaries")
t1 = time.time()
nrecs, ndays = dbmanager.backfill_day_summary()
tdiff = time.time() - t1
if nrecs:
_msg = "Processed %d records to backfill %d day summaries in %.2f seconds" % (nrecs,
ndays,
tdiff)
else:
_msg = "Daily summaries up to date."
loginf("WdArchive:", _msg)