예제 #1
0
    def extractRecordFrom(self, archive, time_ts):
        """Get a record from the archive database. 
        
        This is a general version that works for:
          - WeatherUnderground
          - PWSweather
          - CWOP
        It can be overridden and specialized for additional protocols.
        
        archive: An instance of weewx.archive.Archive
        
        time_ts: The record desired as a unix epoch time.
        
        returns: A dictionary of weather values"""
        
        sod_ts = weeutil.weeutil.startOfDay(time_ts)
        
        # Get the data record off the archive database:
        sqlrec = archive.getSql(REST.sql_select, (time_ts,))
        # There is no reason why the record would not be in the database,
        # but check just in case:
        if sqlrec is None:
            raise SkippedPost("Non existent record %s" % (weeutil.weeutil.timestamp_to_string(time_ts),))

        # Make a dictionary out of the types:
        datadict = dict(zip(REST.archive_types, sqlrec))
        
        # CWOP says rain should be "rain that fell in the past hour".  WU says
        # it should be "the accumulated rainfall in the past 60 min".
        # Presumably, this is exclusive of the archive record 60 minutes before,
        # so the SQL statement is exclusive on the left, inclusive on the right.
        datadict['rain'] = archive.getSql("SELECT SUM(rain) FROM archive WHERE dateTime>? AND dateTime<=?",
                                         (time_ts - 3600.0, time_ts))[0]

        # Similar issue, except for last 24 hours:
        datadict['rain24'] = archive.getSql("SELECT SUM(rain) FROM archive WHERE dateTime>? AND dateTime<=?",
                                            (time_ts - 24*3600.0, time_ts))[0]

        # NB: The WU considers the archive with time stamp 00:00 (midnight) as
        # (wrongly) belonging to the current day (instead of the previous
        # day). But, it's their site, so we'll do it their way.  That means the
        # SELECT statement is inclusive on both time ends:
        datadict['dayRain'] = archive.getSql("SELECT SUM(rain) FROM archive WHERE dateTime>=? AND dateTime<=?", 
                                              (sod_ts, time_ts))[0]

        # All these online weather sites require US units. 
        if datadict['usUnits'] == weewx.US:
            # It's already in US units.
            return datadict
        else:
            # It's in something else. Perform the conversion
            datadict_us = weewx.units.StdUnitConverters[weewx.US].convertDict(datadict)
            # Add the new unit system
            datadict_us['usUnits'] = weewx.US
            return datadict_us
예제 #2
0
    def test_get_records(self):
        # Add a bunch of records:
        with weewx.archive.Archive.open_with_create(self.archive_db_dict, archive_schema) as archive:
            archive.addRecord(genRecords())

        # Now fetch them:
        with weewx.archive.Archive.open(self.archive_db_dict) as archive:
            # Test getSql:
            bar0 = archive.getSql("SELECT barometer FROM archive WHERE dateTime=?", (start_ts,))
            self.assertEqual(bar0[0], barfunc(0))
            
            # Test genSql:
            for (irec,_row) in enumerate(archive.genSql("SELECT barometer FROM archive;")):
                self.assertEqual(_row[0], barfunc(irec))
                
            # Try getRecord():
            target_ts = timevec[nrecs/2]
            _rec = archive.getRecord(target_ts)
            # Check that the missing windSpeed is None, then remove it in order to do the compare:
            self.assertEqual(_rec.pop('windSpeed'), None)
            self.assertEqual(expected_record(nrecs/2), _rec)
            
            # Try finding the nearest neighbor below
            target_ts = timevec[nrecs/2] + interval/100
            _rec = archive.getRecord(target_ts, max_delta=interval/50)
            # Check that the missing windSpeed is None, then remove it in order to do the compare:
            self.assertEqual(_rec.pop('windSpeed'), None)
            self.assertEqual(expected_record(nrecs/2), _rec)

            # Try finding the nearest neighbor above
            target_ts = timevec[nrecs/2] - interval/100
            _rec = archive.getRecord(target_ts, max_delta=interval/50)
            # Check that the missing windSpeed is None, then remove it in order to do the compare:
            self.assertEqual(_rec.pop('windSpeed'), None)
            self.assertEqual(expected_record(nrecs/2), _rec)
            
            # Try finding a neighbor too far away:
            target_ts = timevec[nrecs/2] - interval/2
            _rec = archive.getRecord(target_ts, max_delta=interval/50)
            self.assertEqual(_rec, None)
            
        # Now try fetching them as vectors:
        with weewx.archive.Archive.open(self.archive_db_dict) as archive:
            barvec = archive.getSqlVectors('barometer', start_ts, stop_ts)
            # Recall that barvec will be a 2-way tuple. The first element is the value tuple of
            # the time vector, the second of the data vector.
            self.assertEqual(barvec[0], ([timefunc(irec) for irec in range(nrecs)], "unix_epoch", "group_time"))
            self.assertEqual(barvec[1], ([barfunc(irec)  for irec in range(nrecs)], "inHg",       "group_pressure"))

        # Now try fetching the vectora gain, but using aggregation.
        # Start by setting up a generator function that will return the records to be
        # included in each aggregation
        gen = gen_included_recs(timevec, start_ts, stop_ts, 6*interval)
        with weewx.archive.Archive.open(self.archive_db_dict) as archive:
            barvec = archive.getSqlVectors('barometer', start_ts, stop_ts, aggregate_interval=6*interval, aggregate_type='avg')
            n_expected = int(nrecs / 6)
            self.assertEqual(n_expected, len(barvec[0][0]))
            for irec in range(n_expected):
                # Get the set of records to be included in this aggregation:
                recs = gen.next()
                # Make sure the timestamp of the aggregation interval is the same as the last
                # record to be included in the aggregation:
                self.assertEqual(timevec[max(recs)], barvec[0][0][irec])
                # Calculate the expected average of the records included in the aggregation.
                expected_avg = sum((barfunc(i) for i in recs)) / len(recs)
                # Compare them.
                self.assertAlmostEqual(expected_avg, barvec[1][0][irec])
예제 #3
0
    def test(config_path):
        
        weewx.debug = 1
        try :
            config_dict = configobj.ConfigObj(config_path, file_error=True)
        except IOError:
            print "Unable to open configuration file ", config_path
            exit()
            
        # Open up the main archive database 
        archiveFilename = os.path.join(config_dict['Station']['WEEWX_ROOT'], 
                                       config_dict['Archive']['archive_file'])
        archive = weewx.archive.Archive(archiveFilename)

        statsFilename = os.path.join(config_dict['Station']['WEEWX_ROOT'], 
                                     config_dict['Stats']['stats_file'])

        conn = sqlite3.connect(statsFilename)
        conn.row_factory = sqlite3.Row
        cursor=conn.cursor()

        # Start out by getting a date that exists in the database.
        # Select the 10th record to check. 
        cursor.execute("SELECT dateTime FROM barometer LIMIT 2 OFFSET 10")
        
        # This gets the start time of the test day:
        testrow = cursor.fetchone()
        if not testrow:
            print "Cannot get a test row from the typeStats database. Perhaps it is not initialized??"
            exit()
        start_ts = testrow['dateTime']

        # And this gets the end of the test day:
        testrow = cursor.fetchone()
        stop_ts = testrow['dateTime']
        
        # No need to leave these lying around:
        cursor.close()
        conn.close()

        print "start time=", weeutil.weeutil.timestamp_to_string(start_ts)
        print "stop time= ", weeutil.weeutil.timestamp_to_string(stop_ts)
        # Make sure it's a start of day:
        assert(start_ts == weeutil.weeutil.startOfDay(start_ts))

        # OK, now open up the typeStats database using the class StatsReadonlyDb:
        statsDb = StatsReadonlyDb(statsFilename)
        
        allStats = statsDb.day(start_ts)

        # Test it against some types
        # Should really do a test for 'wind' as well.
        # Should also test monthly, yearly summaries
        for stats_type in ('barometer', 'outTemp', 'inTemp', 'heatindex'):
            print "\n***************** %s ********************" % stats_type
            # Get the StatsDict for this day and this stats_type:
            typeStats = statsDb.getStatsForType(stats_type, start_ts)
        
            # Now test all the aggregates:
            for aggregate in ('min', 'max', 'sum', 'count'):
                # Compare to the main archive:
                res = archive.getSql("SELECT %s(%s) FROM archive WHERE dateTime>? AND dateTime <=?;" % (aggregate, stats_type), start_ts, stop_ts)
                # From StatsDb:
                typeStats_res = typeStats.__getattribute__(aggregate)
                allStats_res  = allStats[stats_type].__getattribute__(aggregate)
                print "%s: results from stats database using getStatsForType(): " % aggregate, typeStats_res
                print "%s: results from stats database using day():         " % aggregate, allStats_res
                print "%s: result from running SQL on the main archive:     " % aggregate, res[0]
                assert(typeStats_res == res[0])
                assert(allStats_res == res[0])
                
                # Check the times of min and max as well:
                if aggregate in ('min','max'):
                    res2 = archive.getSql("SELECT dateTime FROM archive WHERE %s = ? AND dateTime>? AND dateTime <=?" % (stats_type,), res[0], start_ts, stop_ts)
                    stats_time =  typeStats.__getattribute__(aggregate+'time')
                    print aggregate+'time: from main archive:   ', weeutil.weeutil.timestamp_to_string(res2[0])
                    print aggregate+'time: from typeStats database: ', weeutil.weeutil.timestamp_to_string(stats_time)
                    assert( stats_time == res2[0])
        
        print "PASSES\n"