Category Archives: Code Bits

Anything that is code-like will be dumped here for WeeWx.

weewx.conf

This is a mostly completed version of weewx.conf. See the weewx category for details of this config.

DO NOT BLINDLY USE THIS CONFIG – IT’LL LIKELY FAIL.

debug = 0
WEEWX_ROOT = /etc/weewx
log_success = True
log_failure = True
socket_timeout = 20
version = 3.9.1
[Station]
	location = "Olathe Kansas"
	latitude = 38.809253
	longitude = -94.781939
	altitude = 1068, foot
	station_type = Vantage
	station_url = https://weewx.potatoforinter.net
	rain_year_start = 1
	week_start = 6
[StdRESTful]
	[[StationRegistry]]
		register_this_station = false
	[[CWOP]]
		enable = true
		station = CWOPStationIDHere
	[[Wunderground]]
		enable = true
		station = WunderGroundStationIDHere
		password = ReplaceMeWithAPassword
		rapidfire = True
	[[MQTT]]
		server_url = mqtt://weewx:ReplaceMeWithAPassword@localhost:1883/
		topic = weather
		unit_system = US
		binding = archive, loop
		aggregation = aggregate
[Vantage]
	type = serial
	port = /dev/ttyUSB0
	baudrate = 19200
	iss_id = 1
	timeout = 4
	wait_before_retry = 1.2
	max_tries = 4
	model_type = 2
	driver = weewx.drivers.vantage
[StdReport]
	SKIN_ROOT = /etc/weewx/skins/
	HTML_ROOT = /var/www/html/
	data_binding = wx_binding
	report_timing = * * * * *
	log_success = True
	log_failure = True
	skin = Belchertown
	[[Highcharts_Belchertown]]
		HTML_ROOT = /var/www/html/
		skin = Highcharts_Belchertown
	[[Belchertown]]
		HTML_ROOT = /var/www/html/
		skin = Belchertown
	[[[Extras]]]
		belchertown_root_url = "https://weewx.potatoforinter.net"
		site_title = "Southern Olathe KS Weather"
		forecast_enabled = 0
		earthquake_enabled = 0
		twitter_enabled = 0
		twitter_owner = bctrainers
		mqtt_websockets_enabled = 1
		mqtt_websockets_host = "weewx.potatoforinter.net"
		mqtt_websockets_port = 2884
		mqtt_websockets_ssl = 1
		mqtt_websockets_topic = "weather/loop"
		disconnect_live_website_visitor = "9600000"
	[[Defaults]]
		[[[Units]]]
			[[[[Groups]]]]
				group_altitude = foot
				group_degree_day = degree_F_day
				group_pressure = inHg
				group_rain = inch
				group_rainrate = inch_per_hour
				group_speed = mile_per_hour
				group_speed2 = mile_per_hour2
				group_temperature = degree_F
			[[[[StringFormats]]]]
				centibar = %.0f
				cm = %.2f
				cm_per_hour = %.2f
				degree_C = %.1f
				degree_F = %.1f
				degree_compass = %.0f
				foot = %.0f
				hPa = %.1f
				hour = %.1f
				inHg = %.3f
				inch = %.2f
				inch_per_hour = %.2f
				km_per_hour = %.0f
				km_per_hour2 = %.1f
				knot = %.0f
				knot2 = %.1f
				mbar = %.1f
				meter = %.0f
				meter_per_second = %.1f
				meter_per_second2 = %.1f
				mile_per_hour = %.0f
				mile_per_hour2 = %.1f
				mm = %.1f
				mmHg = %.1f
				mm_per_hour = %.1f
				percent = %.0f
				second = %.0f
				uv_index = %.1f
				volt = %.1f
				watt_per_meter_squared = %.0f
				NONE = "   N/A"
			[[[[Labels]]]]
				day = " day", " days"
				hour = " hour", " hours"
				minute = " minute", " minutes"
				second = " second", " seconds"
				NONE = ""
			[[[[TimeFormats]]]]
				hour = %H:%M
				day = %X
				week = %X (%A)
				month = %x %X
				year = %x %X
				rainyear = %x %X
				current = %x %X
				ephem_day = %X
				ephem_year = %x %X
			[[[[Ordinates]]]]
				directions = N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW, N/A
				[[[[[DegreeDays]]]]]
					heating_base = 65, degree_F
					cooling_base = 65, degree_F
				[[[[[Trend]]]]]
					time_delta = 10800
					time_grace = 300
		[[[Labels]]]
			hemispheres = N, S, E, W
			latlon_formats = %02d, %03d, %05.2f
			[[[[Generic]]]]
				barometer = Barometer
				dewpoint = Dew Point
				ET = ET
				heatindex = Heat Index
				inHumidity = Inside Humidity
				inTemp = Inside Temperature
				outHumidity = Humidity
				outTemp = Outside Temperature
				radiation = Radiation
				rain = Rain
				rainRate = Rain Rate
				UV = UV Index
				windDir = Wind Direction
				windGust = Gust Speed
				windGustDir = Gust Direction
				windSpeed = Wind Speed
				windchill = Wind Chill
				windgustvec = Gust Vector
				windvec = Wind Vector
				extraTemp1 = Temperature1
				extraTemp2 = Temperature2
				extraTemp3 = Temperature3
				rxCheckPercent = Signal Quality
				txBatteryStatus = Transmitter Battery
				windBatteryStatus = Wind Battery
				rainBatteryStatus = Rain Battery
				outTempBatteryStatus = Outside Temperature Battery
				inTempBatteryStatus = Inside Temperature Battery
				consBatteryVoltage = Console Battery
				heatingVoltage = Heating Battery
				supplyVoltage = Supply Voltage
				referenceVoltage = Reference Voltage
		[[[Almanac]]]
			moon_phases = New, Waxing crescent, First quarter, Waxing gibbous, Full, Waning gibbous, Last quarter, Waning crescent
[StdConvert]
	target_unit = US
[StdCalibrate]
	[[Corrections]]
#foo = foo + 0.2
[StdQC]
	[[MinMax]]
		barometer = 26, 32.5, inHg
		pressure = 24, 34.5, inHg
		outTemp = -40, 120, degree_F
		inTemp = 10, 120, degree_F
		outHumidity = 0, 100
		inHumidity = 0, 100
		windSpeed = 0, 120, mile_per_hour
		rain = 0, 10, inch
[StdWXCalculate]
	[[Calculations]]
		pressure = prefer_hardware
		barometer = prefer_hardware
		altimeter = prefer_hardware
		windchill = prefer_hardware
		heatindex = prefer_hardware
		dewpoint = prefer_hardware
		inDewpoint = prefer_hardware
		rainRate = prefer_hardware
[StdTimeSynch]
	clock_check = 14400
	max_drift = 2
[Raw]
	data_binding = raw_binding
	data_limit = 0
[StdArchive]
	archive_interval = 60
	archive_delay = 1
	record_generation = hardware
	loop_hilo = True
	data_binding = wx_binding
[DataBindings]
	[[wx_binding]]
		database = archive_mysql
		table_name = archive
		manager = weewx.wxmanager.WXDaySummaryManager
		schema = schemas.wview.schema
	[[raw_binding]]
		database = raw_mysql
		table_name = raw
		manager = weewx.manager.Manager
		schema = user.raw.schema
[Databases]
	[[archive_mysql]]
		database_type = mysql
		database_name = weewx
	[[raw_mysql]]
		database_type = mysql
		database_name = weewx_rapid
[DatabaseTypes]
	[[mysql]]
		driver = weedb.mysql
		host = IP.IP.IP.IP
		user = ReplaceMeWithAUserName
		password = ReplaceMeWithAPassword
[Engine]
	[[Services]]
		prep_services = weewx.engine.StdTimeSynch
		data_services = ,
		process_services = weewx.engine.StdConvert, weewx.engine.StdCalibrate, weewx.engine.StdQC, weewx.wxservices.StdWXCalculate
		archive_services = weewx.engine.StdArchive, user.raw.RawService
		restful_services = weewx.restx.StdStationRegistry, weewx.restx.StdWunderground, weewx.restx.StdPWSweather, weewx.restx.StdCWOP, weewx.restx.StdWOW, weewx.restx.StdAWEKAS, user.mqtt.MQTT
		report_services = weewx.engine.StdPrint, weewx.engine.StdReport

raw.py

This is for raw, real time, loop data from a davis weather station. It’s been ever so slightly modified to persist data forever at a value of 0 via weewx.conf.

[Raw]
     data_binding = raw_binding
     data_limit = 0

The following code goes in place to /usr/share/weewx/user/raw.py

import syslog
import time
import weeutil.weeutil
import weewx
import weewx.engine
import weewx.manager
from weewx.engine import StdService

VERSION = "0.4.1-lh-bc"

#
# 2015-12-28 Modified by Luc Heijst to work with weewx version 3.3.1
# 2019-01-15 Minor tweak by Brett C to persist data... for a long time.
#

if weewx.__version__ < "3":
    raise weewx.UnsupportedFeature("weewx 3 is required, found %s" % weewx.__version__)

schema = [
    ('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
    ('usUnits', 'INTEGER NOT NULL'),
    #('interval', 'INTEGER NOT NULL DEFAULT \'1\''),
    ('barometer', 'REAL'),
    #('pressure', 'REAL'),
    #('altimeter', 'REAL'),
    ('inTemp', 'REAL'),
    ('outTemp', 'REAL'),
    ('inHumidity', 'REAL'),
    ('outHumidity', 'REAL'),
    ('windSpeed', 'REAL'),
    ('windDir', 'REAL'),
    #('windGust', 'REAL'),
    #('windGustDir', 'REAL'),
    ('rainRate', 'REAL'),
    ('rain', 'REAL'), # rain, was: dayRain
    ('dewpoint', 'REAL'),
    ('windchill', 'REAL'),
    ('heatindex', 'REAL'),
    #('rxCheckPercent', 'REAL'),
    ('dayET', 'REAL'), # ET
    ('radiation', 'REAL'),
    ('UV', 'REAL'),
    ('extraTemp1', 'REAL'),
    ('extraTemp2', 'REAL'),
    ('extraTemp3', 'REAL'),
    ('soilTemp1', 'REAL'),
    ('soilTemp2', 'REAL'),
    ('soilTemp3', 'REAL'),
    ('soilTemp4', 'REAL'),
    ('leafTemp1', 'REAL'),
    ('leafTemp2', 'REAL'),
    ('extraHumid1', 'REAL'),
    ('extraHumid2', 'REAL'),
    ('soilMoist1', 'REAL'),
    ('soilMoist2', 'REAL'),
    ('soilMoist3', 'REAL'),
    ('soilMoist4', 'REAL'),
    ('leafWet1', 'REAL'),
    ('leafWet2', 'REAL'),
    ('txBatteryStatus', 'REAL'),
    ('consBatteryVoltage', 'REAL')]
    #('hail', 'REAL'),
    #('hailRate', 'REAL'),
    #('heatingTemp', 'REAL'),
    #('heatingVoltage', 'REAL'),
    #('supplyVoltage', 'REAL'),
    #('referenceVoltage', 'REAL'),
    #('windBatteryStatus', 'REAL'),
    #('rainBatteryStatus', 'REAL'),
    #('outTempBatteryStatus', 'REAL'),
    #('inTempBatteryStatus', 'REAL')i

def get_default_binding_dict():
    return {'database': 'raw_mysql',
            'manager': 'weewx.manager.Manager',
            'table_name': 'raw',
            'schema': 'user.raw.schema'}

class RawService(StdService):

    def __init__(self, engine, config_dict):
        self.config_dict = config_dict
        super(RawService, self).__init__(engine, config_dict)
        syslog.syslog(syslog.LOG_INFO, "raw: service version is %s" % VERSION)

        d = config_dict.get('Raw', {})
        self.dataLimit = int(d.get('data_limit', 24))

        # get the database parameters we need to function
        self.binding = d.get('data_binding', 'raw_binding')
        self.dbm = self.engine.db_binder.get_manager(data_binding=self.binding, initialize=True)

        # be sure schema in database matches the schema we have
        dbcol = self.dbm.connection.columnsOf(self.dbm.table_name)
        dbm_dict = weewx.manager.get_manager_dict(
            config_dict['DataBindings'], config_dict['Databases'], self.binding)
        memcol = [x[0] for x in dbm_dict['schema']]
        if dbcol != memcol:
            raise Exception('raw: schema mismatch: %s != %s' % (dbcol, memcol))

        self.lastLoopDateTime = 0
        self.lastPrunedDateTime = 0
        self.bind(weewx.NEW_LOOP_PACKET, self.newLoopPacket)

    def prune_rawdata(self, dbm, ts, max_tries=3, retry_wait=10):
        """remove rawdata older than data_limit hours from the database"""
        sql = "delete from %s where dateTime < %d" % (dbm.table_name, ts)
        for count in range(max_tries):
            try:
                dbm.getSql(sql)
                syslog.syslog(syslog.LOG_INFO, 'raw: deleted rawdata prior to %s' % weeutil.weeutil.timestamp_to_string(ts))
                break
            except Exception, e:
                syslog.syslog(syslog.LOG_ERR, 'raw: prune failed (attempt %d of %d): %s' % ((count + 1), max_tries, e))
                syslog.syslog(syslog.LOG_INFO, 'raw: waiting %d seconds before retry' % retry_wait)
                time.sleep(retry_wait)
        else:
            raise Exception('raw: prune failed after %d attemps' % max_tries)

    def newLoopPacket(self, event):
        packet = event.packet
        prune_period = 300
        # It's possible for records with duplicate dateTimes - this occurs when an archive packet
        # is processed since the LOOP packets are queued up and then returned immediately when
        # looping resumes, coupled with the fact that for Vantage Pro consoles the dateTime value is
        # added by weewx. So, for database storage, skip the duplicates until we get a new one to
        # avoid a duplicate key error, but publish them all to redis regardless.
        dateTime = packet['dateTime']
        if dateTime != self.lastLoopDateTime:
            self.dbm.addRecord(packet)
            self.lastLoopDateTime = dateTime
        if dateTime > (self.lastPrunedDateTime + prune_period):
            if self.dataLimit is not 0:
                ts = ((dateTime - (self.dataLimit * 3600)) / prune_period) * prune_period  # preset on 5-min boundary
                self.prune_rawdata(self.dbm, ts, 2, 5)
            self.lastPrunedDateTime = dateTime