OutOfSpan: Attempt to merge an accumulator whose timespan is not a subset

512 views
Skip to first unread message

Kris Benson

unread,
Jul 9, 2014, 10:25:27 AM7/9/14
to weewx...@googlegroups.com
I had been running weewx with the Simulator for a while, then on Sunday, switched to using real weather station data, and MySQL for a backend (previously it was sqlite).

Ever since this switch, weewx crashes at midnight leaving this in /var/log/messages:
Jul  9 00:00:15 timothy weewx[32177]:     ****  Traceback (most recent call last):
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 954, in main
Jul  9 00:00:15 timothy weewx[32177]:     ****      engine.run()
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 189, in run
Jul  9 00:00:15 timothy weewx[32177]:     ****      self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 210, in dispatchEvent
Jul  9 00:00:15 timothy weewx[32177]:     ****      callback(event)
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 550, in post_loop
Jul  9 00:00:15 timothy weewx[32177]:     ****      self.statsDb.updateHiLo(self.old_accumulator)
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/stats.py", line 298, in updateHiLo
Jul  9 00:00:15 timothy weewx[32177]:     ****      _stats_dict.updateHiLo(accumulator)
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/accum.py", line 221, in updateHiLo
Jul  9 00:00:15 timothy weewx[32177]:     ****      raise OutOfSpan("Attempt to merge an accumulator whose timespan is not a subset")
Jul  9 00:00:15 timothy weewx[32177]:     ****  OutOfSpan: Attempt to merge an accumulator whose timespan is not a subset

/var/log/syslog reports slightly different info:
Jul  9 00:00:14 timothy weewx[32177]: wxengine: Shut down StdReport thread.
Jul  9 00:00:14 timothy weewx[32177]: restx: Shut down CWOP thread.
Jul  9 00:00:14 timothy weewx[32177]: restx: Shut down PWSWeather thread.
Jul  9 00:00:15 timothy weewx[32177]: restx: Shut down Wunderground-RF thread.
Jul  9 00:00:15 timothy weewx[32177]: restx: Shut down StationRegistry thread.
Jul  9 00:00:15 timothy weewx[32177]: wxengine: Caught unrecoverable exception in wxengine:
Jul  9 00:00:15 timothy weewx[32177]:     ****  Attempt to merge an accumulator whose timespan is not a subset
Jul  9 00:00:15 timothy weewx[32177]:     ****  Traceback (most recent call last):
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 954, in main
Jul  9 00:00:15 timothy weewx[32177]:     ****      engine.run()
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 189, in run
Jul  9 00:00:15 timothy weewx[32177]:     ****      self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 210, in dispatchEvent
Jul  9 00:00:15 timothy weewx[32177]:     ****      callback(event)
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 550, in post_loop
Jul  9 00:00:15 timothy weewx[32177]:     ****      self.statsDb.updateHiLo(self.old_accumulator)
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/stats.py", line 298, in updateHiLo
Jul  9 00:00:15 timothy weewx[32177]:     ****      _stats_dict.updateHiLo(accumulator)
Jul  9 00:00:15 timothy weewx[32177]:     ****    File "/usr/share/weewx/weewx/accum.py", line 221, in updateHiLo
Jul  9 00:00:15 timothy weewx[32177]:     ****      raise OutOfSpan("Attempt to merge an accumulator whose timespan is not a subset")
Jul  9 00:00:15 timothy weewx[32177]:     ****  OutOfSpan: Attempt to merge an accumulator whose timespan is not a subset
Jul  9 00:00:15 timothy weewx[32177]:     ****  Exiting.

Any thoughts?

I've removed the old database files, and also removed the NOAA files in case that's what was trying to accumulate to.  The system runs perfectly well all day, it's just at the stroke of midnight that it has a hiccup.

Thanks!

Andrew Milner

unread,
Jul 9, 2014, 10:51:27 AM7/9/14
to weewx...@googlegroups.com
Are you doing some housekeeping / cron tasks at midnight - or why does weewx appear to start to shutdown??  Is there anything in the logs from 00:00:00 to 00:00:15 that could throw some additional light??

Kris Benson

unread,
Jul 9, 2014, 10:58:44 AM7/9/14
to weewx...@googlegroups.com
Hi Andrew,

Not that I've configured.  I'm using the Debian apt installation of weewx, but there's nothing starting at midnight in my crontabs.

Also, there's nothing relevant in the logs before that -- the previous entries are of weewx's normal operation at 23:59.

-kb


--
You received this message because you are subscribed to a topic in the Google Groups "Weewx user's group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/weewx-user/bT0mCwMScuI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to weewx-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Andrew Milner

unread,
Jul 9, 2014, 11:15:46 AM7/9/14
to weewx...@googlegroups.com
Are your computer and weatherstation both set with the correct time and time zone??  Weewx's 'daily' activities tend to happen (I think) at midnight UTC rather than midnight local and your post implies the oddities occurred at midnight local time - whilst cron and other general computer tasks etc tend to be running on local time.

I'm sure Tom, Matthew and the more knowledgeable users will chip in with much better pointers than I can offer though!!

Kris Benson

unread,
Jul 9, 2014, 11:21:44 AM7/9/14
to weewx...@googlegroups.com
Hi Andrew,

The weather station is time agnostic.  The computer's time and time zone are correct.
timothy:/home/kris# date -R
Wed, 09 Jul 2014 09:20:50 -0600
timothy:/home/kris# date -Ru
Wed, 09 Jul 2014 15:20:52 +0000
timothy:/home/kris# date
Wed Jul  9 09:21:06 MDT 2014
timothy:/home/kris# date -u
Wed Jul  9 15:21:08 UTC 2014


Thanks for your help!

-kb

Thomas Keffer

unread,
Jul 9, 2014, 8:46:19 PM7/9/14
to weewx-user
No obvious reason I can see why this would be happening.

Couple questions:

What is your timezone offset? I want to determine what the UTC time was when it crashed.

Did you delete the stats database, as well as the archive database in MySQL?

Once I bracket the failure, I can send you an instrumented version of stats.py that should give more information. Unfortunately, I'm on a boat right now, so it's tough to do very sophisticated forensics.

-tk


--
You received this message because you are subscribed to the Google Groups "Weewx user's group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to weewx-user+...@googlegroups.com.

Kris Benson

unread,
Jul 10, 2014, 11:16:29 AM7/10/14
to weewx...@googlegroups.com
Hi Thomas,

Thanks for your response!

Here's the output of 'date' from my system that should give you what you need:
timothy:/home/kris# date -R
Wed, 09 Jul 2014 09:20:50 -0600
timothy:/home/kris# date -Ru
Wed, 09 Jul 2014 15:20:52 +0000
timothy:/home/kris# date
Wed Jul  9 09:21:06 MDT 2014
timothy:/home/kris# date -u
Wed Jul  9 15:21:08 UTC 2014

I deleted both of the sqlite databases, and then enabled MySQL.  I've tried deleting the oldest records in the MySQL stats and archive tables, but that didn't help either.

-kb


--
You received this message because you are subscribed to a topic in the Google Groups "Weewx user's group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/weewx-user/bT0mCwMScuI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to weewx-user+...@googlegroups.com.

Thomas Keffer

unread,
Jul 10, 2014, 11:21:45 AM7/10/14
to weewx-user
So you are 6 hours behind UTC.

1. Did you by any chance change the timezone or time information after setting up MySQL? I'm thinking the stats database was started using one time offset, but then the offset was changed.

2. Can you stop weewx, drop the stats database, then restart weewx? It will automatically be rebuilt.

-tk

Kris Benson

unread,
Jul 10, 2014, 11:26:06 AM7/10/14
to weewx...@googlegroups.com
1. Nope.  Time zone hasn't changed in years (well before I'd even heard of weewx).

2. Done.  I don't know how to trigger this (aside from changing the time to after midnight, which may create more problems than it solves), so I'll have to wait until tomorrow to let you know if this fixed it.

-kb

Kris Benson

unread,
Jul 11, 2014, 10:15:27 AM7/11/14
to weewx...@googlegroups.com
Hi Thomas,

No change last night -- still died at 00:00:16.

Any other suggestions?

-kb

Andrew Milner

unread,
Jul 11, 2014, 11:21:08 AM7/11/14
to weewx...@googlegroups.com
I remain intrigued by this occurring at midnight local time (well 15 seconds afterwards).

Can you post the log from 2350 - 0005 and also a copy of your cron table and root's cron table and cron.daily?  In my bones I am sure it is cron related!!!

...

Kris Benson

unread,
Jul 11, 2014, 12:16:22 PM7/11/14
to weewx...@googlegroups.com

Ok, so since this started, I've added a cron job to get weewx running again at 00:05 -- so that's where the restart (and new PIDs) at 00:05 is coming from.  There's no sense in me going back to 23:50 -- from 23:50-23:59, all you'll see are the five lines here at 23:59 repeated.

Jul 10 23:59:02 timothy weewx[9226]: archive: added record 2014-07-10 23:58:12 MDT (1405058292) to database 'wx_weewx'; table 'archive'
Jul 10 23:59:02 timothy weewx[9226]: cheetahgenerator: generated 1 'SummaryByMonth' files for StandardReport in 0.09 seconds
Jul 10 23:59:03 timothy weewx[9226]: cheetahgenerator: generated 1 'SummaryByYear' files for StandardReport in 0.36 seconds
Jul 10 23:59:03 timothy weewx[9226]: cheetahgenerator: generated 12 'ToDate' files for StandardReport in 0.38 seconds
Jul 10 23:59:06 timothy weewx[9226]: genimages: Generated 26 images for StandardReport in 3.23 seconds
Jul 11 00:00:16 timothy weewx[9226]:     ****  Traceback (most recent call last):
Jul 11 00:00:16 timothy weewx[9226]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 954, in main
Jul 11 00:00:16 timothy weewx[9226]:     ****      engine.run()
Jul 11 00:00:16 timothy weewx[9226]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 189, in run
Jul 11 00:00:16 timothy weewx[9226]:     ****      self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Jul 11 00:00:16 timothy weewx[9226]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 210, in dispatchEvent
Jul 11 00:00:16 timothy weewx[9226]:     ****      callback(event)
Jul 11 00:00:16 timothy weewx[9226]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 550, in post_loop
Jul 11 00:00:16 timothy weewx[9226]:     ****      self.statsDb.updateHiLo(self.old_accumulator)
Jul 11 00:00:16 timothy weewx[9226]:     ****    File "/usr/share/weewx/weewx/stats.py", line 298, in updateHiLo
Jul 11 00:00:16 timothy weewx[9226]:     ****      _stats_dict.updateHiLo(accumulator)
Jul 11 00:00:16 timothy weewx[9226]:     ****    File "/usr/share/weewx/weewx/accum.py", line 221, in updateHiLo
Jul 11 00:00:16 timothy weewx[9226]:     ****      raise OutOfSpan("Attempt to merge an accumulator whose timespan is not a subset")
Jul 11 00:00:16 timothy weewx[9226]:     ****  OutOfSpan: Attempt to merge an accumulator whose timespan is not a subset
Jul 11 00:05:01 timothy weewx[10992]: wxengine: Initializing weewx version 2.6.3
Jul 11 00:05:01 timothy weewx[10992]: wxengine: Using Python 2.7.3 (default, Mar 14 2014, 11:57:14) #012[GCC 4.7.2]
Jul 11 00:05:01 timothy weewx[10992]: wxengine: pid file is /var/run/weewx.pid
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Using configuration file /etc/weewx/weewx.conf
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Loading station type AcuLink (weewx.drivers.aculink)
Jul 11 00:05:01 timothy weewx[10994]: wxengine: StdConvert target unit is 0x10
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Record generation will be attempted in 'hardware'
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Using archive interval of 72 seconds
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Using archive database: archive_mysql
Jul 11 00:05:01 timothy weewx[10994]: stats: stats database up to date.
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Using stats database: stats_mysql
Jul 11 00:05:01 timothy weewx[10994]: restx: StationRegistry: Station will be registered.
Jul 11 00:05:01 timothy weewx[10994]: restx: Wunderground-RF: Data for station IALBERTA290 will be posted
Jul 11 00:05:01 timothy weewx[10994]: restx: PWSWeather: Data for station ALBERTA290 will be posted
Jul 11 00:05:01 timothy weewx[10994]: restx: CWOP: Data for station EW5507 will be posted
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Starting up weewx version 2.6.3
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Clock error is -0.07 seconds (positive is fast)
Jul 11 00:05:01 timothy weewx[10994]: wxengine: Starting main packet loop.

It's running as root.  root's user crontab is empty.

Here's /etc/crontab:
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.


SHELL
=/bin/sh
PATH
=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin


# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#


*/5 *   * * *   root    /share/nest/nest-cron.php
30 20   * * 0-5 root    /share/nest/nest-fan.php on
30 22   * * 0-5 root    /share/nest/nest-fan.php auto
5  0    * * *   root    /etc/init.d/weewx stop; /etc/init.d/weewx start


As you can see, cron.daily is also irrelevant, as it doesn't run until after 6 am.

Also, cron.hourly runs at 17 minutes after the hour, so that, too isn't it.

(FWIW, no experienced admin would schedule the nightly tasks to happen between midnight and 3am.  The biggest issue is the time between 01:00 and 03:00 -- in areas that observe DST, in the fall 01:00-02:00 happens twice that night and in the spring, 02:00-03:00 doesn't happen at all that night.  The time between 00:00 and 01:00 is just not worth playing with...)

Does *any* of this interface with the hardware driver???  That is the only part of this weewx installation that isn't perfectly standard.

mwall

unread,
Jul 11, 2014, 12:31:44 PM7/11/14
to weewx...@googlegroups.com
On Friday, July 11, 2014 12:16:22 PM UTC-4, Kris Benson wrote:
Does *any* of this interface with the hardware driver???  That is the only part of this weewx installation that isn't perfectly standard.

i'll play. 

could you post the part of your driver that creates loop records?  or perhaps the entire driver if you do not mind?

does this behavior happen only with mysql, or do you get it with sqlite too?

m

Kris Benson

unread,
Jul 11, 2014, 12:59:25 PM7/11/14
to weewx...@googlegroups.com

Ok, so I'm using a driver that was based on Simulator and modified by another user.  It interfaces with a drop file provided by tcpdump from the Aculink bridge.

I've not tried this driver with sqlite -- I changed to MySQL at the same time that I set up the real driver.

Here is the content of my driver:

#    This simulator.py file has been modified to work with
#    with the AcuRite AcuLink Bridge.  Don't blame Tom for
#    this ugly hack.  Someone should write a proper driver.
#    george.nincehelser (at) gmail.com
#
#    Copyright (c) 2012 Tom Keffer
#
#    See the file LICENSE.txt for your full rights.
#
#    $Revision: 1124 $
#    $Author: tkeffer $
#    $Date: 2013-03-27 16:00:35 -0400 (Wed, 27 Mar 2013) $
#
"""Console simulator for the weewx weather system"""


from __future__ import with_statement
import math
import time

import weedb
import weeutil.weeutil
import weewx.abstractstation
import weewx.wxformulas

def loader(config_dict, engine):

    # This loader uses a bit of a hack to have the simulator resume at a later
    # time. It's not bad, but I'm not enthusiastic about having special
    # knowledge about the database in a driver, albeit just the loader.

    start_ts = resume_ts = None
    if 'start' in config_dict['Simulator']:
        # A start has been specified. Extract the time stamp.
        start_tt = time.strptime(config_dict['Simulator']['start'], "%Y-%m-%d %H:%M")
        start_ts = time.mktime(start_tt)
        # If the 'resume' keyword is present and True, then get the last archive
        # record out of the database and resume with that.
        if int(config_dict['Simulator'].get('resume', 1)):
            import weewx.archive
            # Resume with the last time in the database. If there is no such
            # time, then fall back to the time specified in the configuration
            # dictionary.
            archive_db = config_dict['StdArchive']['archive_database']
            archive_db_dict = config_dict['Databases'][archive_db]
            try:
                with weewx.archive.Archive.open(archive_db_dict) as archive:
                    resume_ts = archive.lastGoodStamp()
            except weedb.OperationalError:
                pass
        else:
            # The resume keyword is not present. Start with the seed time:
            resume_ts = start_ts

    station = Simulator(start_time=start_ts, resume_time=resume_ts, **config_dict['Simulator'])

    return station

class Simulator(weewx.abstractstation.AbstractStation):
    """AcuLink Internet Bridge"""

    def __init__(self, **stn_dict):
        """Initialize the simulator

        NAMED ARGUMENTS:

        loop_interval: The time (in seconds) between emitting LOOP packets. [Optional. Default is 2.5]

        start_time: The start (seed) time for the generator in unix epoch time [Optional. If 'None',
                    or not present, then the present time will be used.]

        resume_time: The start time for the loop. [Optional. If 'None',
                     or not present, then start_time will be used].

        mode: Required. One of either:
            'simulator': Real-time simulator. It will sleep between emitting LOOP packets.
            'generator': Emit packets as fast as it can (useful for testing).
        """

        self.loop_interval = float(stn_dict.get('loop_interval', 2.5))
        if 'start_time' in stn_dict and stn_dict['start_time'] is not None:
            # A start time has been specified. We are not in real time mode.
            self.real_time = False
            # Extract the generator start time:
            start_ts = float(stn_dict['start_time'])
            # If a resume time keyword is present (and it's not None),
            # then have the generator resume with that time.
            if 'resume_time' in stn_dict and stn_dict['resume_time'] is not None:
                self.the_time = float(stn_dict['resume_time'])
            else:
                self.the_time = start_ts
        else:
            # No start time specified. We are in realtime mode.
            self.real_time = True
            start_ts = self.the_time = time.time()

        self.mode = stn_dict['mode']

        # The following doesn't make much meteorological sense, but it is easy to program!
        self.observations = {'outTemp'    : Observation(magnitude=20.0,  average= 50.0, period=24.0, phase_lag=14.0, start=start_ts),
                             'barometer'  : Observation(magnitude=1.0,   average= 30.1, period=48.0, phase_lag= 0.0, start=start_ts),
                             'windSpeed'  : Observation(magnitude=10.0,  average=  5.0, period=48.0, phase_lag=24.0, start=start_ts),
                             'windDir'    : Observation(magnitude=360.0, average=180.0, period=48.0, phase_lag= 0.0, start=start_ts),
                             'humidity'   : Observation(magnitude=30.0,  average= 50.0, period=48.0, phase_lag= 0.0, start=start_ts),
                             'rain'       : Rain(rain_start=0, rain_length=3, total_rain=0.2, loop_interval=self.loop_interval)}

    def genLoopPackets(self):

        while True:

            # If we are in simulator mode, sleep first (as if we are gathering
            # observations). If we are in generator mode, don't sleep at all.
            if self.mode == 'simulator':
                # Determine how long to sleep
                if self.real_time:
                    # We are in real time mode. Try to keep synched up with the
                    # wall clock
                    sleep_time = self.the_time + self.loop_interval - time.time()
                    if sleep_time > 0:
                        time.sleep(sleep_time)
                else:
                    # A start time was specified, so we are not in real time. Just sleep
                    # the appropriate interval
                    time.sleep(self.loop_interval)

            # Update the simulator clock:
            self.the_time += self.loop_interval

            # Because a packet represents the measurements observed over the
            # time interval, we want the measurement values at the middle
            # of the interval.
            avg_time = self.the_time - self.loop_interval/2.0

            _packet = {'dateTime': int(self.the_time+0.5),
                       'usUnits' : weewx.US }
            for obs_type in self.observations:
                _packet[obs_type] = self.observations[obs_type].value_at(avg_time)

            temptest = None

            while temptest is None:
                wxdata = dict()

                with open("/home/kris/wxdata") as f:
                    for line in f:
                        eq_index = line.find('=')
                        wxdata_name = line[:eq_index].strip()
                        number = float(line[eq_index + 1:].strip())
                        wxdata[wxdata_name] = number

                f.close()
                temptest = wxdata.get('temp', None)

            print(wxdata)

            _packet['outTemp'] = wxdata['temp']
            _packet['outHumidity'] = wxdata['humi']
            _packet['inTemp'] = wxdata['in_temp']
            _packet['inHumidity'] = wxdata['in_humid']
            _packet['barometer'] = wxdata['baro']
            _packet['windSpeed'] = wxdata['wspd']
            _packet['extraTemp1'] = wxdata['extraTemp1']
            _packet['extraHumid1'] = wxdata['extraHumid1']
            _packet['extraTemp2'] = wxdata['extraTemp2']
            _packet['heatingTemp'] = wxdata['heatingTemp']

            if wxdata['wspd'] >=1:
                    _packet['windDir'] = wxdata['wdir']
            else:
                    _packet['windDir'] = None

            _packet['rain'] = wxdata['rain'] / 14.4

            _packet['windGust'] = None
            _packet['WindGustDir'] = None

            _packet['dewpoint'] = weewx.wxformulas.dewpointF(_packet['outTemp'], _packet['outHumidity'])

            _packet['windchill'] = weewx.wxformulas.windchillF(_packet['outTemp'], _packet['windSpeed'])
            _packet['heatindex'] = weewx.wxformulas.heatindexF(_packet['outTemp'], _packet['outHumidity'])

            yield _packet

    def getTime(self):
        return self.the_time

    @property
    def hardware_name(self):
        return "AcuLink Internet Bridge"

class Observation(object):

    def __init__(self, magnitude=1.0, average=0.0, period=96.0, phase_lag=0.0, start=None):
        """Initialize an observation function.

        magnitude: The value at max. The range will be twice this value
        average: The average value, averaged over a full cycle.
        period: The cycle period in hours.
        phase_lag: The number of hours after the start time when the observation hits its max
        start: Time zero for the observation in unix epoch time."""

        if not start:
            raise ValueError("No start time specified")
        self.magnitude = magnitude
        self.average   = average
        self.period    = period * 3600.0
        self.phase_lag = phase_lag * 3600.0
        self.start     = start

    def value_at(self, time_ts):
        """Return the observation value at the given time.

        time_ts: The time in unix epoch time."""

        phase = 2.0 * math.pi * (time_ts - self.start - self.phase_lag) / self.period
        return self.magnitude * math.cos(phase) + self.average


class Rain(object):

    bucket_tip = 0.01

    def __init__(self, rain_start=0, rain_length=1, total_rain=0.1, loop_interval=None):
        """Initialize a rain simulator"""
        npackets = 3600 * rain_length / loop_interval
        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.packet_number = 0

    def value_at(self, time_ts):
        time_tt = time.localtime(time_ts)
        secs_since_midnight = time_tt.tm_hour * 3600 + time_tt.tm_min * 60.0 + time_tt.tm_sec
        if self.rain_start < secs_since_midnight <= self.rain_end:
            amt = Rain.bucket_tip if self.packet_number % self.period == 0 else 0.0
            self.packet_number += 1
        else:
            self.packet_number = 0
            amt = 0
        return amt



if __name__ == "__main__":

    station = Simulator(mode='simulator',loop_interval=2.0)
    for packet in station.genLoopPackets():
        print weeutil.weeutil.timestamp_to_string(packet['dateTime']), packet



Andrew Milner

unread,
Jul 11, 2014, 1:50:45 PM7/11/14
to weewx...@googlegroups.com
and what is in your cron tables and cron.daily???????????

Kris Benson

unread,
Jul 11, 2014, 1:56:00 PM7/11/14
to weewx...@googlegroups.com
Hi Andrew,

I already posted the relevant parts.  The cron tables are empty.  Only the /etc/crontab is used.

cron.daily doesn't run until 6am (that's in /etc/crontab) -- and is not relevant.  For kicks, here is what's there:

apache2  apt  aptitude  bsdmainutils  dpkg  exim4-base  logrotate  man-db  mdadm  passwd  samba

Those amount to 772 lines, so I'm not posting their content here.  They're unmodified from the package distributions of those applications in the Debian distro.

-kb


--
You received this message because you are subscribed to a topic in the Google Groups "Weewx user's group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/weewx-user/bT0mCwMScuI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to weewx-user+...@googlegroups.com.

Andrew Milner

unread,
Jul 11, 2014, 2:07:11 PM7/11/14
to weewx...@googlegroups.com
Well I just read the first four lines of your driver ..... and think that sums up everything quite nicely!!!!!!  Weewx is the best sw out there and it itself works just fine ... now what happens when you start modifying and adding things is another story entirely - although Matthew appears to have bitten the bullet or sipped from the poisoned chalice ......

Kris Benson

unread,
Jul 11, 2014, 2:13:53 PM7/11/14
to weewx...@googlegroups.com

Andrew: you're quite right, from what I've seen.  The only thing that I don't like about it is that it doesn't (out of the box) support my hardware! :)

FWIW, I wouldn't have heard about weewx unless I had seen George's site on how he got his AcuLink system working... so it is a two-way street.

I posted looking for help because the trace didn't seem to come back to this file.  I'm not a python coder (tried it a few years back and hated it, so stuck with perl & PHP), so reading through this doesn't get me very far.

-kb

mwall

unread,
Jul 11, 2014, 2:15:03 PM7/11/14
to weewx...@googlegroups.com
kris,

could you try the attached driver instead of the one you are using?

1) put aculink.py in the weewx user folder

cp aculink.py /home/weewx/bin/user

2) modify weewx.conf to include these:

[Station]                                                                    
    ...
    station_type = AcuLink                                                   
[AcuLink]                                                                    
    loop_interval = 2
    wxdata_path = /home/kris/wxdata
    driver = user.aculink

3) start weewx

sudo /home/weewx/bin/weewxd /home/weewx/weewx.conf

if that runs properly, then stop weewx, run it as a daemon, then wait to see if all is well after the witching hour.

this driver simply reads the aculink data file then stuffs those data into a weewx loop packet.  it gets rid of some time stuff (left over from the simulator code) that might have been causing bogus timestamps.

you can test the driver directly like this:

cd /home/weewx
PYTHONPATH=bin python bin/user/aculink.py

when run directly, it will fail because the AcuLink class is not properly initialized with a dict.  i leave that fix as an exercise to the reader :)

m

aculink.py

Andrew Milner

unread,
Jul 11, 2014, 2:22:00 PM7/11/14
to weewx...@googlegroups.com
As we would say from the North of England Matthew ..... eeeee - yr a grand'un!!!!!

Kris Benson

unread,
Jul 11, 2014, 2:37:02 PM7/11/14
to weewx...@googlegroups.com
wow, Matthew, thanks!

By "runs properly" do you mean outputs this:

LOOP:   2014-07-11 12:33:41 MDT (1405103621) {'windGust': None, 'barometer': 1020.28645, 'windchill': 21.599999999999998, 'dewpoint': 11.314292093106443, 'outHumidity': 52.0, 'heatindex': 21.599999999999998, 'rain': 0.0, 'heatingTemp': 16.0, 'windDir': 112.5, 'outTemp': 21.599999999999998, 'windSpeed': 3.218688, 'inHumidity': 52.0, 'inTemp': 20.549999999999997, 'extraHumid1': 47.0, 'extraTemp1': 23.1, 'dateTime': 1405103621, 'extraTemp2': 21.4, 'usUnits': 16, 'WindGustDir': None}

continuously?

There's no delay between them -- I have a tonne with that same timestamp.  Just checking to make sure that's by design.

-kb


mwall

unread,
Jul 11, 2014, 2:43:14 PM7/11/14
to weewx...@googlegroups.com
On Friday, July 11, 2014 2:37:02 PM UTC-4, Kris Benson wrote:
wow, Matthew, thanks!

By "runs properly" do you mean outputs this:

LOOP:   2014-07-11 12:33:41 MDT (1405103621) {'windGust': None, 'barometer': 1020.28645, 'windchill': 21.599999999999998, 'dewpoint': 11.314292093106443, 'outHumidity': 52.0, 'heatindex': 21.599999999999998, 'rain': 0.0, 'heatingTemp': 16.0, 'windDir': 112.5, 'outTemp': 21.599999999999998, 'windSpeed': 3.218688, 'inHumidity': 52.0, 'inTemp': 20.549999999999997, 'extraHumid1': 47.0, 'extraTemp1': 23.1, 'dateTime': 1405103621, 'extraTemp2': 21.4, 'usUnits': 16, 'WindGustDir': None}

continuously?

There's no delay between them -- I have a tonne with that same timestamp.  Just checking to make sure that's by design.

-kb

that was a combination of by design and by oversight.  attached is the driver (v0.3) that respects the loop_interval parameter.  it should emit data every 2.5 seconds, or at whatever loop_interval you specify in weewx.conf.  it still needs better error handling wrt the wxdata file, but i don't know where that file is coming from.

could you explain how you are generating the wxdata file?

m
 
aculink.py

Kris Benson

unread,
Jul 11, 2014, 3:35:36 PM7/11/14
to weewx...@googlegroups.com

Wow... not just a new driver today, but a bug fix, too! :)

I certainly can certainly explain how the wxdata file is being generated!

I adopted George's process (ref: http://nincehelser.com/ipwx/ ) and added a few other little features.

Basically, my Linux box has two NICs operating in bridge mode.  The AcuRite AcuLink Bridge is the only thing (currently) on one of those NICs.

Traffic from the bridge is captured via tcpdump:
tcpdump -A -n -p -i eth2 -s0 -w - tcp dst port 80 | stdbuf -oL strings -n8 | stdbuf -oL egrep "mt=5N1|mt=pressure|mt=tower"

and then piped to a parser:

#!/usr/bin/perl

# Copyright 2013 George D. Nincehelser
# Modification 2014 by Kris Benson

# id=24C86E014F4C&sensor=01086&mt=5N1x31&windspeed=A001660000&winddir=6&rainfall=A0000000&battery=normal&rssi=2  # backyard
# id=24C86E014F4C&sensor=01086&mt=5N1x38&windspeed=A003270000&humidity=A0480&temperature=A024222222&battery=normal&rssi=2  # backyard

# id=24C86E014F4C&sensor=01438&mt=tower&humidity=A0160&temperature=A019800000&battery=normal&rssi=2  # basement
# id=24C86E014F4C&sensor=11583&mt=tower&humidity=A0440&temperature=A026100000&battery=normal&rssi=2  # front porch
# id=24C86E014F4C&mt=pressure&C1=442D&C2=0C77&C3=010E&C4=027D&C5=87E7&C6=178F&C7=09C4&A=07&B=19&C=06&D=09&PR=95EF&TR=8902T  # base

$celsius        = '';
$farenheit      = '';
$humidity       = '';
$celsius2        = '';
$farenheit2      = '';
$humidity2       = '';
$celsius3        = '';
$farenheit3      = '';
$humidity3       = '';
$windspeed      = '';
$winddir        = '';
$rainfall       = '';
$raintotal      = '0';
$pressure       = '';
$pressure_in    = '';
$nestinfo       = '';
$verbose = 0;

while ($line = <STDIN> ) {
  $index = index ($line, 'mt=pressure');
  if ($index != -1) {
    $c1 = substr $line, index ($line, 'C1=') + 3, 4;
    $c2 = substr $line, index ($line, 'C2=') + 3, 4;
    $c3 = substr $line, index ($line, 'C3=') + 3, 4;
    $c4 = substr $line, index ($line, 'C4=') + 3, 4;
    $c5 = substr $line, index ($line, 'C5=') + 3, 4;
    $c6 = substr $line, index ($line, 'C6=') + 3, 4;
    $c7 = substr $line, index ($line, 'C7=') + 3, 4;
    $a  = substr $line, index ($line, 'A=') + 2, 2;
    $b  = substr $line, index ($line, 'B=') + 2, 2;
    $c  = substr $line, index ($line, 'C=') + 2, 2;
    $d  = substr $line, index ($line, 'D=') + 2, 2;
    $pr = substr $line, index ($line, 'PR=') + 3, 4;
    $tr = substr $line, index ($line, 'TR=') + 3, 4;

    $c1 = hex ($c1);
    $c2 = hex ($c2);
    $c3 = hex ($c3);
    $c4 = hex ($c4);
    $c5 = hex ($c5);
    $c6 = hex ($c6);
    $c7 = hex ($c7);
    $a  = hex ($a);
    $b  = hex ($b);
    $c  = hex ($c);
    $d  = hex ($d);
    $pr = hex ($pr);
    $tr = hex ($tr);

    $d1 = $pr;
    $d2 = $tr;

    if ($d2 >= $c5) {
      $dut = $d2-$c5-(($d2-$c5)/2**7) * (($d2-$c5)/2**7)*$a/2**$c;
    } else {
      $dut = $d2-$c5-(($d2-$c5)/2**7) * (($d2-$c5)/2**7)*$b/2**$c;
    };

    $off = ($c2 + ($c4 - 1024) * $dut / 2**14) * 4;
    $sens = $c1 + $c3 * $dut / 2**10;
    $x = $sens * ($d1 - 7168) / 2**14 - $off;
    $p = $x * 10 / 2**5 + $c7;

    $t = 250 + $dut*$c6/2**16-$dut/2**$d;

    $barocorrection = 760+440;

    $p = $p + $barocorrection;

    $pressure = sprintf ("%.2f", $p / 10);
    $pressure_in = sprintf ("%.4f", $p / 338.6 );
  } else {
    # if the pressure was recorded, then no other data is forthcoming from this line, so we can separate all this

    # this is for the multi-sensor thing
    $index = index ($line, 'sensor=01086');
    if ($index != -1) {
      #
      # Wind direction is reported as a single hex digit
      # Also seems to be using a non-standard Gray Code
      #
      $index = index ($line, 'winddir');
      if ($index != -1) {
          $winddir_frag = substr $line, $index + 8, 1;
          if ($winddir_frag eq '5' ) { $winddir = 0 };
          if ($winddir_frag eq '7' ) { $winddir = 22.5 };
          if ($winddir_frag eq '3' ) { $winddir = 45 };
          if ($winddir_frag eq '1' ) { $winddir = 67.5 };
          if ($winddir_frag eq '9' ) { $winddir = 90 };
          if ($winddir_frag eq 'B' ) { $winddir = 112.5 };
          if ($winddir_frag eq 'F' ) { $winddir = 135 };
          if ($winddir_frag eq 'D' ) { $winddir = 157.5 };
          if ($winddir_frag eq 'C' ) { $winddir = 180 };
          if ($winddir_frag eq 'E' ) { $winddir = 202.5 };
          if ($winddir_frag eq 'A' ) { $winddir = 225 };
          if ($winddir_frag eq '8' ) { $winddir = 247.5 };
          if ($winddir_frag eq '0' ) { $winddir = 270 };
          if ($winddir_frag eq '2' ) { $winddir = 292.5 };
          if ($winddir_frag eq '6' ) { $winddir = 315 };
          if ($winddir_frag eq '4' ) { $winddir = 337.5 };
      };

      $index = index ($line, 'rainfall');

      if ($index != -1) {
        $rainfall_frag = substr $line, $index + 10, 6;
        $rainfall = $rainfall_frag / 2540;
        $raintotal = $raintotal + $rainfall;
      };

      # Wind speed is reported as centimeters per second
      # Convert to miles per hour by dividing by 44.7
      # Rounded to nearest MPH
      $index = index ($line, 'windspeed');
      if ($index != -1) {
        $wind_frag = substr $line, $index + 11, 5;
        $windspeed = sprintf ("%.0f", $wind_frag / 44.7);
      };

      if (index ($line, 'temperature') != -1) {
        $temp_frag = substr $line, index ($line, 'temperature') + 13, 4;
        $celsius = $temp_frag / 10;
        $farenheit = $celsius * 9/5 + 32;
      };

      if (index ($line, 'humidity') != -1) {
        $humid_frag = substr $line, index ($line, 'humidity') + 11, 3;
        $humidity = $humid_frag / 10;
      };
    } else {
      # for when it's not the multi-sensor
      # sensor=11583 = front porch
      $index = index ($line, 'sensor=11583');
      if ($index != -1) {
        if (index ($line, 'temperature') != -1) {
          $temp2_frag = substr $line, index ($line, 'temperature') + 13, 4;
          $celsius2 = $temp2_frag / 10;
          $farenheit2 = $celsius2 * 9/5 + 32;
        };

        if (index ($line, 'humidity') != -1) {
          $humid2_frag = substr $line, index ($line, 'humidity') + 11, 3;
          $humidity2 = $humid2_frag / 10;
        };
      } else {
        # for when it's not the multi-sensor
        # sensor=01438 = inside
        $index = index ($line, 'sensor=01438');
        if ($index != -1) {
          if (index ($line, 'temperature') != -1) {
            $temp3_frag = substr $line, index ($line, 'temperature') + 13, 4;
            $celsius3 = $temp3_frag / 10;
            $farenheit3 = $celsius3 * 9/5 + 32;
          };

          # this sensor doesn't do humidity, just transmits 16%
          #if (index ($line, 'humidity') != -1) {
          #  $humid3_frag = substr $line, index ($line, 'humidity') + 11, 3;
          #  $humidity3 = $humid3_frag / 10;
          #};
        };
      };
    };
  };

  # data gathered from this line, let's update the display and record file
  if ($verbose == 1) {
    print "\033[2J";    #clear the screen
    print "\033[0;0H"; #jump to 0,0

    use POSIX qw(strftime);
    print strftime("%a, %d %b %Y %H:%M:%S %z", localtime(time())) . "\n";

    print "\n $line \n";
    print "temperature C = $celsius\n" if ($celsius != '');
    print "humidity % = $humidity\n" if ($humidity != '');
    print "temperature (front) C = $celsius2\n" if ($celsius2 != '');
    print "humidity (front) % = $humidity2\n" if ($humidity2 != '');
    print "temperature (inside) C = $celsius3\n" if ($celsius3 != '');
    print "wind speed MPH = $windspeed\n" if ($windspeed != '');
    print "wind direction degrees = $winddir\n" if ($winddir != '');
    print "rain in last 36 seconds inches = $rainfall\n" if ($rainfall != '');
    print "total rain since last restart inches = $raintotal\n" if ($raintotal != '');
    print "absolute pressure in mmHg = $pressure\n" if ($pressure != '');
    print "absolute pressure in inHg = $pressure_in\n" if ($pressure_in != '');
    print $nestinfo;
  }

  open (NESTFILE, '/tmp/nest_current');
  $nestinfo = '';
  open (MYFILE, '>/home/kris/wxdata');
  print MYFILE "temp = $farenheit\n" if ($farenheit != '9999');
  print MYFILE "humi = $humidity\n" if ($humidity != '9999');
  print MYFILE "baro = $pressure_in\n" if ($pressure_in != '9999');
  print MYFILE "wspd = $windspeed\n" if ($windspeed != '9999');
  print MYFILE "wdir = $winddir\n" if ($winddir != '9999');
  print MYFILE "rain = $rainfall\n" if ($rainfall != '9999');
  print MYFILE "extraTemp1 = $farenheit2\n" if ($farenheit2 != '9999');
  print MYFILE "extraHumid1 = $humidity2\n" if ($humidity2 != '9999');
  print MYFILE "extraTemp2 = $farenheit3\n" if ($farenheit3 != '9999');
  foreach $nestline (<NESTFILE>) {
    print MYFILE $nestline;
    $nestinfo .= $nestline;
  }
  close (MYFILE);
  close (NESTFILE);
};



This parser generates the file (including another file that is generated by my Nest thermostat's monitoring cron job) and leaves it for the weewx driver.

Make sense?

mwall

unread,
Jul 11, 2014, 4:26:11 PM7/11/14
to weewx...@googlegroups.com
On Friday, July 11, 2014 3:35:36 PM UTC-4, Kris Benson wrote:
Wow... not just a new driver today, but a bug fix, too! :)

I certainly can certainly explain how the wxdata file is being generated!

I adopted George's process (ref: http://nincehelser.com/ipwx/ ) and added a few other little features.

nicely done!

you could easily create a nest driver for weewx, or perhaps a nest service to augment aculink data (or any other weather station data) with nest data.  the nest has a pretty simple http api, no?

you might want to map the rssi and battery values into the weewx database so that you can monitor signal strength and battery status.

for example, the driver for the te923 hardware uses this mapping:

        txBatteryStatus =      batteryUV # uv sensor
        windBatteryStatus =    batteryWind # wind sensor
        rainBatteryStatus =    batteryRain # rain sensor
        outTempBatteryStatus = battery1 # remote t/h sensor
        # WARNING: the following are not in the default schema                 
        extraBatteryStatus1 =  battery2  # remote t/h sensor 2
        extraBatteryStatus2 =  battery3  # remote t/h sensor 3
        extraBatteryStatus3 =  battery4  # remote t/h sensor 4
        extraBatteryStatus4 =  battery5  # remote t/h sensor 5

you would have to extend the default weewx schema to include a signal strength (rssi) for each remote sensor, since the default schema includes only rxCheckPercent.

of course the first step is to make sure that the aculink.py driver works properly with the basic data !

m

Kris Benson

unread,
Jul 11, 2014, 10:53:37 PM7/11/14
to weewx...@googlegroups.com
Thanks, again, Matthew.

I'll wait until tonight's witching hour to see -- if everything is golden tomorrow, it'll be time to look at some of these features. :)

One other thing I'd like to add is some sort of error tolerance -- i.e. if the field is missing from the wxdata file, then it shouldn't fail catastrophically (maybe your recoded driver doesn't, but the one I was using until today does).

The thought of using a service for Nest might be good -- but their API is S.L.O.W.  As in, a refresh of my status page (which pulls the info and just prints the variables) takes about 11 seconds.  That's *every* refresh of it.  Hence why I do it once every five minutes and keep some of the data for later. :)

Kris Benson

unread,
Jul 12, 2014, 3:04:27 PM7/12/14
to weewx...@googlegroups.com
Sadly, this didn't solve it.

Still had the same error messages.

Any other thoughts?

mwall

unread,
Jul 12, 2014, 3:59:17 PM7/12/14
to weewx...@googlegroups.com
On Saturday, July 12, 2014 3:04:27 PM UTC-4, Kris Benson wrote:
Sadly, this didn't solve it.

Still had the same error messages.

Any other thoughts?


this does not address the OutOfSpan error, but the attached driver (aculink.py v0.4) will not fail when it encounters bogus data in the wxdata file or when the wxdata file does not exist.

could you try switching back to sqlite and start with no weewx.sdb and no stats.sdb files?  see if the problem is specific to mysql...

m
aculink.py

Kris Benson

unread,
Jul 12, 2014, 10:08:47 PM7/12/14
to weewx...@googlegroups.com
Thanks again!

I'll modify the parser now to not put data it doesn't have (when first started, it takes a minute or so to get data from all the sensors).

I'd prefer to leave the sqlite thing as a last-ditch effort -- right now, I have data in MySQL and would like to be able to keep the historical record going... nicer graphs that way. :)

I've got a fairly suitable workaround (restart weewx at 00:05), so this isn't a big deal one way or the other... but would be nice to get figured out. :)

-kb


--

mwall

unread,
Jul 12, 2014, 10:24:38 PM7/12/14
to weewx...@googlegroups.com
On Saturday, July 12, 2014 10:08:47 PM UTC-4, Kris Benson wrote:
I'll modify the parser now to not put data it doesn't have (when first started, it takes a minute or so to get data from all the sensors).

I'd prefer to leave the sqlite thing as a last-ditch effort -- right now, I have data in MySQL and would like to be able to keep the historical record going... nicer graphs that way. :)


kris,

you can leave your current instance of weewx as it is.  install another instance in /home/weewx (or anywhere else) using setup.py, and run the new instance using the aculink driver and sqlite.  since the aculink driver is simply reading from file there will be no conflict.

it would really help to know whether this problem is specific to mysql...

m

Thomas Keffer

unread,
Jul 13, 2014, 12:13:59 AM7/13/14
to weewx-user
Regarding the OutOfSpan exception. 

The code in stats.py basically says, "Get the start of the day for the accumulator, use it to retrieve the running total for that day, then merge the accumulator into it."

Somehow, the exception is getting raised in that last step.

There may be a lurking bug somewhere in the code. Either the start of day is not getting calculated correctly (but why then would we be able to retrieve the running total?), or the exception is getting incorrectly raised. 

This is why I was interested in the time zone offset: so I could calculate the true start of day and see if it compares to what weewx thinks it is.

Matthew, if you want to take this farther, you could instrument method StatsDb.updateHiLo in stats.py.

Otherwise, if I remember, I'll take it up when I get back.

-tk


--
You received this message because you are subscribed to the Google Groups "Weewx user's group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to weewx-user+...@googlegroups.com.

Andrew Milner

unread,
Jul 13, 2014, 12:57:19 AM7/13/14
to weewx...@googlegroups.com
Could the driver be generating (or obtaining) timestamps that are in local time rather than UTC perhaps?  I run MySQL on a Pi with FineOffset and have never seen this issue.  It HAS to be related to local/UTC time since the issue occurs at midnight local - but then I am baffled as to why it should apparently work in sqlite but not MySQL. Seems to defy logic - and that makes it illogical!!

I won't waste anyone's time with speculating further since clearly this requires some debug code to pin down precisely.

Andrew Milner

unread,
Jul 13, 2014, 1:04:26 AM7/13/14
to weewx...@googlegroups.com
Just had a thought ...... is the MySQL server on the same computer that was used to give us the timezone information in an earlier post, or is it being accessed over a network? If the server is elsewhere is the computer the MySQL server is on also set to the same timezone?

Kris Benson

unread,
Jul 14, 2014, 12:09:15 PM7/14/14
to weewx...@googlegroups.com
Thanks, guys.

Matthew: I haven't had a chance to deal with this -- busy weekend.  I installed from the Debian apt source -- is there any reason I can't just run a second copy of the same instance, but point it at the different conf file?

Andrew: they're all on the same box.

Andrew Milner

unread,
Jul 14, 2014, 12:17:28 PM7/14/14
to weewx...@googlegroups.com
can you explain exqctly what you are are trying to achieve - rather than how you are going about getting there!!!!   You never answered my question regarding the location of the MySQL server, and this question implies you are are up to something very specific!!!!!

Kris Benson

unread,
Jul 14, 2014, 12:22:27 PM7/14/14
to weewx...@googlegroups.com
Andrew: I did answer your question in my previous e-mail: "Andrew: they're all on the same box."

I'm not doing anything complicated -- just storing the data collected.  I don't know what you're not understanding -- the only "specific" thing I'm doing here is collecting data from a previously unsupported set of hardware.  Matthew has definitely gone above and beyond in coding up that driver, for which I am much appreciative!

-kb


--
You received this message because you are subscribed to a topic in the Google Groups "Weewx user's group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/weewx-user/bT0mCwMScuI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to weewx-user+...@googlegroups.com.

Andrew Milner

unread,
Jul 14, 2014, 12:56:00 PM7/14/14
to weewx...@googlegroups.com
So why so  why do y

Andrew Milner

unread,
Jul 14, 2014, 12:56:49 PM7/14/14
to weewx...@googlegroups.com
So why so  why do you have a need for two instances?


On Monday, 14 July 2014 19:22:27 UTC+3, Kris Benson wrote:

mwall

unread,
Jul 14, 2014, 1:11:30 PM7/14/14
to weewx...@googlegroups.com
On Monday, July 14, 2014 12:09:15 PM UTC-4, Kris Benson wrote:
Matthew: I haven't had a chance to deal with this -- busy weekend.  I installed from the Debian apt source -- is there any reason I can't just run a second copy of the same instance, but point it at the different conf file?


kris,

you can run multiple instances of weewx from a single installation.  be sure to invoke each with a different weewx.conf, and be sure to have each weewx.conf refer to distinct resources, specifically different databases and different HTML_ROOT.

run your 'regular' instance using /etc/init.d/weewx as you normally would:

sudo /etc/init.d/weewx start

then run the test instance directly, for example:

sudo weewxd /etc/weewx/weewx-test.conf

m

Kris Benson

unread,
Jul 14, 2014, 1:12:23 PM7/14/14
to weewx...@googlegroups.com
Because Matthew wants to see if it works OK under sqlite, and I don't want to give up recording in MySQL.

-kb

Kris Benson

unread,
Jul 14, 2014, 1:24:39 PM7/14/14
to weewx...@googlegroups.com
Okee dokee.

I've got it running.  Will let you know tomorrow if it crashes overnight.

-kb


--
You received this message because you are subscribed to a topic in the Google Groups "Weewx user's group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/weewx-user/bT0mCwMScuI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to weewx-user+...@googlegroups.com.

Kris Benson

unread,
Jul 15, 2014, 12:51:19 PM7/15/14
to weewx...@googlegroups.com

Sure enough, that instance crashed at midnight as well.  So it's clearly not a DB choice issue.

mwall

unread,
Jul 21, 2014, 3:05:02 PM7/21/14
to weewx...@googlegroups.com
kris,

here is an instrumented accum.py (for weewx 2.6.4).

mv /usr/share/weewx/weewx/accum.py /usr/share/weewx/weewx/accum.py-orig
cp ~/Downloads/accum.py /usr/share/weewx/weewx/accum.py
/etc/init.d/weewx stop
/etc/init.d/weewx start

this should still fail with OutOfSpan exception, but it will tell us what is out of span.

m
accum.py

Kris Benson

unread,
Jul 21, 2014, 3:14:45 PM7/21/14
to weewx...@googlegroups.com
Ok, thanks!

I've put it in place... will let you know results tomorrow.

-kb


--

Kris Benson

unread,
Jul 22, 2014, 11:24:19 AM7/22/14
to weewx...@googlegroups.com
Alright, here's what we got:

Jul 22 00:00:16 timothy weewx[28553]:     ****  Traceback (most recent call last):
Jul 22 00:00:16 timothy weewx[28553]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 954, in main
Jul 22 00:00:16 timothy weewx[28553]:     ****      engine.run()
Jul 22 00:00:16 timothy weewx[28553]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 189, in run
Jul 22 00:00:16 timothy weewx[28553]:     ****      self.dispatchEvent(weewx.Event(weewx.POST_LOOP))
Jul 22 00:00:16 timothy weewx[28553]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 210, in dispatchEvent
Jul 22 00:00:16 timothy weewx[28553]:     ****      callback(event)
Jul 22 00:00:16 timothy weewx[28553]:     ****    File "/usr/share/weewx/weewx/wxengine.py", line 550, in post_loop
Jul 22 00:00:16 timothy weewx[28553]:     ****      self.statsDb.updateHiLo(self.old_accumulator)
Jul 22 00:00:16 timothy weewx[28553]:     ****    File "/usr/share/weewx/weewx/stats.py", line 298, in updateHiLo
Jul 22 00:00:16 timothy weewx[28553]:     ****      _stats_dict.updateHiLo(accumulator)
Jul 22 00:00:16 timothy weewx[28553]:     ****    File "/usr/share/weewx/weewx/accum.py", line 221, in updateHiLo
Jul 22 00:00:16 timothy weewx[28553]:     ****      raise OutOfSpan("Attempt to merge an accumulator whose timespan is not a subset: start: %s:%s stop: %s:%s" % (accumulator.timespan.start, self.timespan.start, accumulator.timespan.stop, self.timespan.stop))
Jul 22 00:00:16 timothy weewx[28553]:     ****  OutOfSpan: Attempt to merge an accumulator whose timespan is not a subset: start: 1406008740:1406008800 stop: 1406008812:1406095200

Let me know what else to do... :)

Thanks!

-kb

Thomas Keffer

unread,
Aug 2, 2014, 1:07:33 PM8/2/14
to weewx-user
Kris,

I've finally had a chance to take a look at this. The problem has to do with your rather odd archive interval, 72 seconds. There is an algorithmic assumption inside weewx that archive intervals are multiples of 60 seconds.

Is there any way of changing it?

If not, I'll see if I can modify the routine that calculates the start of an archive interval.

-tk



--
You received this message because you are subscribed to the Google Groups "Weewx user's group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to weewx-user+...@googlegroups.com.

Kris Benson

unread,
Aug 2, 2014, 4:51:02 PM8/2/14
to weewx...@googlegroups.com

Yeah, I can try that.

I think I remember trying 60, but it broke on first interval.

I'll give it a go on Mon or Tues.


--
-kb

Thomas Keffer

unread,
Aug 2, 2014, 5:17:37 PM8/2/14
to weewx-user
Send me the log if it does!

-tk

Kris Benson

unread,
Aug 6, 2014, 10:31:26 PM8/6/14
to weewx...@googlegroups.com
It appears to have solved it!

Thanks, Thomas and Matthew!!!

-kb
Reply all
Reply to author
Forward
0 new messages