Hello,

Just a bit of background: I currently have a VP2 and I recently bought a 
WS3000 with 8 sensors to monitor the inside temperature in various places. 
What I would like to do is to store all the data in the same database. My 
goal is to enhance each VP2 record with the temperature coming from the 
WS3000.

I found absolutely everything I needed to do this in the documentation, so 
congrats, you did a really great job documenting weewx and the 
possibilities of this tool are just amazing. I love it!

Anyway, here is what I did:
- rewrote a brand new driver for the WS3000, which works with the standard 
weewx code (no need to use the USB branch).
- created a small service that gets the current sensor values from the 
WS3000 and adds them to each new record (and loop packet as well).
- modified the database schema to include extraTemp1 to 8 and extraHumid1 
to 8, to store the data from the WS3000.

This all seems to work quite well (so far tested with the Simulator only), 
except for a weird problem: all the temperature are properly converted to 
the appropriate metrics, except for extraTemp8.
Is there some kind of limit to the number of values that get converted 
with StdConvert?

NOTE: WS3000 reports temperature in °C. I modified the Simulator to do the 
same, but I store the values in the database using °F.

Any clue on what's wrong?

Here is a typical loop packet:
LOOP:   2018-01-18 23:32:07 CET (1516314727) altimeter: None, appTemp: 
106.743627453, barometer: None, cloudbase: 1601.11136389, dateTime: 
1516314727, dewpoint: 83.6206936222, extraHumid1: 47, extraHumid2: 46, 
extraHumid3: 48, extraHumid4: 46, extraHumid5: 45, extraHumid6: 44, 
extraHumid7: 47, extraHumid8: 46, extraTemp1: 74.12, extraTemp2: 73.94, 
extraTemp3: 74.12, extraTemp4: 74.12, extraTemp5: 74.12, extraTemp6: 74.3, 
extraTemp7: 74.3, extraTemp8: 23.6, heatindex: 115.825270834, humidex: 
120.858219625, inDewpoint: None, inHumidity: 29.9996112567, inTemp: None, 
maxSolarRad: None, outHumidity: 79.9997084411, outTemp: 90.6655836233, 
pressure: None, radiation: 0, rain: 0.0, usUnits: 1, UV: 0, windchill: 
90.6655836233, windDir: 359.998250647, windGust: 0.000130440063404, 
windGustDir: 359.998250647, windSpeed: 0.000108700052838

=> as you can see, extraTemp8 is still expressed in °C, while all the 
others are in °F.

Thanks!

PS: I attached all the files I am currently using:
- the WS3000 driver
- the data service
- my weewx.conf

-- 
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.
import weewx
import sys
from weewx.engine import StdService


class AddWS300Data(StdService):

    def __init__(self, engine, config_dict):
        # Initialize my superclass first:
        super(AddWS300Data, self).__init__(engine, config_dict)

        # Bind to any new archive record events and new loop record events
        self.bind(weewx.NEW_ARCHIVE_RECORD, self.update_record)
        self.bind(weewx.NEW_LOOP_PACKET, self.update_packet)

        # Load WS3000 driver
        driver = config_dict['WS3000']['driver']
        __import__(driver)
        driver_module = sys.modules[driver]
        loader_function = getattr(driver_module, 'loader')
        self.ws3000 = loader_function(config_dict, self)

    def update_record(self, event):
        self.update_dict(event.record)

    def update_packet(self, event):
        self.update_dict(event.packet)

    def update_dict(self, dict):
        wspacket = self.ws3000.getCurrentValues()
        for key in self.ws3000.sensor_map.keys():
            dict[key] = wspacket[key]
#
#
"""Classes and functions for interfacing with an Ambient Weather WS-3000
station.

The following references were useful for developing this driver. More than simply useful,
in fact, since a lot of material has been directly reused:
    
>From Matthew Wall:
  https://github.com/matthewwall/weewx-hp3000

>From Tom Keffer, the WMR100 driver for weewx
  http://www.weewx.com

NOTE: the HP3000 driver developed by Matthew Wall should also be working
for the WS-3000 station. But various issues led me to rewrite a new driver
on the model of the one for the WMR100. One benefit is that this driver will
work with the "default" version of weewx and doesn't require the usb branch.

"""

import time
import syslog
import usb.core, usb.util
import sys, traceback

import usb

import weewx.drivers
import weewx.wxformulas

DRIVER_NAME = 'WS3000'
DRIVER_VERSION = "0.1"


def loader(config_dict, engine):
    return WS3000(**config_dict[DRIVER_NAME])


def confeditor_loader():
    return WS3000ConfEditor()


def logmsg(level, msg):
    syslog.syslog(level, 'ws3000: %s' % msg)


def logdbg(msg):
    logmsg(syslog.LOG_DEBUG, msg)


def loginf(msg):
    logmsg(syslog.LOG_INFO, msg)


def logerr(msg):
    logmsg(syslog.LOG_ERR, msg)


def tohex(buf):
    """Helper function used to print a byte array in hex format"""
    if buf:
        return "%s (len=%s)" % (' '.join(["%02x" % x for x in buf]), len(buf))
    return ''


class WS3000(weewx.drivers.AbstractDevice):
    """Driver for the WS3000 station."""

    DEFAULT_MAP = {
        'extraTemp1': 't_1',
        'extraTemp2': 't_2',
        'extraTemp3': 't_3',
        'extraTemp4': 't_4',
        'extraTemp5': 't_5',
        'extraTemp6': 't_6',
        'extraTemp7': 't_7',
        'extraTemp8': 't_8',
        'extraHumid1': 'h_1',
        'extraHumid2': 'h_2',
        'extraHumid3': 'h_3',
        'extraHumid4': 'h_4',
        'extraHumid5': 'h_5',
        'extraHumid6': 'h_6',
        'extraHumid7': 'h_7',
        'extraHumid8': 'h_8'}

    COMMANDS = {
        'sensor_values': 0x03,
        'calibration_values': 0x05,
        'interval_value': 0x41,
        'unknown': 0x06,
        'temp_alarm_configuration': 0x08,
        'humidity_alarm_configuration': 0x09,
        'device_configuration': 0x04
    }

    def getCmdName(self, command):
        return self.COMMANDS.keys()[self.COMMANDS.values().index(command)]

    def __init__(self, **stn_dict):
        """Initialize an object of type WS3000.
        
        NAMED ARGUMENTS:
        
        model: Which station model is this?
        [Optional. Default is 'WS3000']

        timeout: How long to wait, in seconds, before giving up on a response
        from the USB port.
        [Optional. Default is 15 seconds]
        
        wait_before_retry: How long to wait before retrying.
        [Optional. Default is 5 seconds]

        max_tries: How many times to try before giving up.
        [Optional. Default is 3]
        
        vendor_id: The USB vendor ID for the WS3000
        [Optional. Default is 0x0483]
        
        product_id: The USB product ID for the WS3000
        [Optional. Default is 0xca01]
        
        interface: The USB interface
        [Optional. Default is 0]
        
        loop_interval: The time (in seconds) between emitting LOOP packets.
        [Optional. Default is 10]
        
        packet_size: The size of the data fetched from the WS3000 during each read.
        [Optional. Default is 64 (0x40)]
        
        """

        # The following variables will in fact be fetched from the device itself.
        # There are anyway declared here with the usual values for the WS3000.
        self.IN_ep = 0x82
        self.OUT_ep = 0x1

        loginf('driver version is %s' % DRIVER_VERSION)
        self.model = stn_dict.get('model', 'WS3000')
        self.record_generation = stn_dict.get('record_generation', 'software')
        self.timeout = float(stn_dict.get('timeout', 15.0))
        self.wait_before_retry = float(stn_dict.get('wait_before_retry', 5.0))
        self.max_tries = int(stn_dict.get('max_tries', 3))
        self.loop_interval = int(stn_dict.get('loop_interval', 10))
        self.vendor_id = int(stn_dict.get('vendor_id', '0x0483'), 0)
        self.product_id = int(stn_dict.get('product_id', '0x5750'), 0)
        self.interface = int(stn_dict.get('interface', 0))
        self.packet_size = int(stn_dict.get('packet_size', 64)) # 0x40
        self.sensor_map = dict(self.DEFAULT_MAP)

        if 'sensor_map' in stn_dict:
            self.sensor_map.update(stn_dict['sensor_map'])
        loginf('sensor map is %s' % self.sensor_map)
        self.device = None
        self.openPort()

    def openPort(self):
        """Establish a connection to the WS3000"""

        # try to find the device using the vend and product id
        self.device = self._findDevice()
        if not self.device:
            logerr("Unable to find USB device (0x%04x, 0x%04x)" %
                   (self.vendor_id, self.product_id))
            raise weewx.WeeWxIOError("Unable to find USB device")
        for line in str(self.device).splitlines():
            logdbg(line)

        # reset device, required if it was previously left in a 'bad' state
        self.device.reset()

        # Detach any interfaces claimed by the kernel
        if self.device.is_kernel_driver_active(self.interface):
            print("Detaching kernel driver")
            self.device.detach_kernel_driver(self.interface)

        # get the interface and IN and OUT end points
        self.device.set_configuration()
        configuration = self.device.get_active_configuration()
        self.interface = usb.util.find_descriptor(
            configuration, bInterfaceNumber=self.interface
        )
        self.OUT_ep = usb.util.find_descriptor(
            self.interface,
            # match the first OUT endpoint
            custom_match= \
                lambda e: \
                    usb.util.endpoint_direction(e.bEndpointAddress) == \
                    usb.util.ENDPOINT_OUT)
        self.IN_ep = usb.util.find_descriptor(
            self.interface,
            # match the first OUT endpoint
            custom_match= \
                lambda e: \
                    usb.util.endpoint_direction(e.bEndpointAddress) == \
                    usb.util.ENDPOINT_IN)

        # The following is normally not required... could be removed?
        try:
            usb.util.claim_interface(self.device, self.interface)
        except usb.USBError, e:
            self.closePort()
            logerr("Unable to claim USB interface: %s" % e)
            raise weewx.WeeWxIOError(e)

    def closePort(self):
        """Tries to ensure that the device will be properly 'unclaimed' by the driver"""
        try:
            usb.util.dispose_resources(self.device)
        except usb.USBError:
            try:
                self.device.reset()
            except:
                pass

    def getCurrentValues(self):
        """Function that only returns the current sensors data.
        Should be used by a data service that will add temperature data to an existing packet, for
        example, since a single measurement would be required in such a case."""

        nberrors = 0
        while nberrors < self.max_tries:
            # Get a stream of raw packets, then convert them
            try:
                command = self.COMMANDS['sensor_values']
                raw = self._getRawData(command)
                data = self._rawToData(raw, command)
                logdbg('data: %s' % data)
                packet = self._dataToWXPacket(data)
                logdbg('packet: %s' % packet)
                return packet
            except usb.USBError:
                print "An error occurred while generating loop packets:", sys.exc_info()
                nberrors += 1
                time.sleep(self.wait_before_retry)
        logerr("Max retries exceeded while fetching USB reports")
        traceback.print_exc(file=sys.stdout)
        raise weewx.RetriesExceeded("Max retries exceeded while fetching USB reports")

    def genLoopPackets(self):
        """Generator function that continuously returns loop packets"""
        try:
            while True:
                packet = self.getCurrentValues()
                yield packet
                time.sleep(self.loop_interval)
        except GeneratorExit:
            pass

    #def genPackets(self):
        # TODO

             
    @property
    def hardware_name(self):
        return self.model
        
    #===============================================================================
    #                         USB functions
    #===============================================================================

    def _findDevice(self):
        """Find the given vendor and product IDs on the USB bus"""
        device = usb.core.find(idVendor=self.vendor_id, idProduct=self.product_id)
        return device

    def _writeUSB(self, buf):
        logdbg("write: %s" % tohex(buf))
        return self.device.write(self.OUT_ep, data=buf, timeout=100)

    def _readUSB(self):
        logdbg("reading " + str(self.packet_size) + " bytes")
        buf = self.device.read(self.IN_ep, self.packet_size, 100)
        if not buf:
            return None
        logdbg("read: %s" % tohex(buf))
        if len(buf) != 64:
            logdbg('read: bad buffer length: %s != 64' % len(buf))
            return None
        if buf[0] != 0x7b:
            logdbg('read: bad first byte: 0x%02x != 0x7b' % buf[0])
            return None
        idx = None
        for i in range(0, len(buf) - 1):
            if buf[i] == 0x40 and buf[i + 1] == 0x7d:
                idx = i
                break
        if idx is None:
            logdbg('read: no terminating bytes in buffer: %s' % tohex(buf))
            return None
        return buf[0: idx + 2]

    # =========================================================================
    # LOOP packet related functions
    #==========================================================================

    def _getRawData(self, command=COMMANDS['sensor_values']):
        """Get a sequence of bytes from the console."""
        sequence = [0x7b, command, 0x40, 0x7d]
        try:
            logdbg("sending request for " + self.getCmdName(command))
            self._writeUSB(sequence)
            logdbg("reading results...")
            buf = self._readUSB()
            return buf
        except:
            print "An error occurred:", sys.exc_info()
            traceback.print_exc(file=sys.stdout)
            raise weewx.IO_ERROR("Error while fetching " + self.getCmdName(command))

    def _rawToData(self, buf, command=COMMANDS['sensor_values']):
        """Convert the raw bytes sent by the console to human readable values."""
        #TODO: implement conversion of other type of data (configuration, calibration, etc.)
        #TODO: even if this probably won't be very useful for weewx.
        logdbg("extracting values for " + self.getCmdName(command))
        logdbg("raw: %s" % buf)
        record = dict()
        if not buf:
            return record
        if command == self.COMMANDS['sensor_values']:
            if len(buf) != 27:
                raise weewx.WeeWxIOError("Incorrect buffer length, failed to read " + self.getCmdName(command))
            record['type'] = self.getCmdName(command)
            for ch in range(8):
                idx = 1 + ch * 3
                if buf[idx] != 0x7f and buf[idx + 1] != 0xff:
                    record['t_%s' % (ch + 1)] = (buf[idx] * 256 + buf[idx + 1]) / 10.0
                if buf[idx + 2] != 0xff:
                    record['h_%s' % (ch + 1)] = buf[idx + 2]
        else:
            logdbg("unknown data: %s" % tohex(buf))
        return record

    def _dataToWXPacket(self, data):
        # prepare the packet for weewx (map sensor data to database fields)
        packet = {'dateTime': int(time.time() + 0.5), 'usUnits': weewx.METRICWX}
        for x in self.sensor_map:
            if self.sensor_map[x] in data:
                packet[x] = data[self.sensor_map[x]]
        return packet

class WS3000ConfEditor(weewx.drivers.AbstractConfEditor):
    @property
    def default_stanza(self):
        return """
[WS3000]
    # This section is for the Ambient Weather WS3000

    # The driver to use
    driver = weewx.drivers.WS3000

    # The station model, e.g., WS3000, WS3000-X3, WS3000-X5 (all the same...)
    model = WS3000
    
    # [Optional] The interval at which loop packets should be generated by the driver
    # Default is 10
    loop_interval = 30
    
    # [Optional] USB vendor ID and product ID, as returned by lsusb. Only required if the device
    # cannot be found with the default values
    # Defaults are 0x0483 and 0x5750
    vendor_id =  0x0483
    product_id = 0x5750
    
    # [Optional] By default, all the sensor values are stored in the extraTemp or extraHumid columns. The assumption here is
    # that the WS3000 is used as a secondary station to enhance another existing station with additional 
    # temperature sensors, and that the usual inTemp, outTemp, etc. are already used by the primary station.
    # NOTE: of course, the database schema must be modified to include the missing columns.
    [[sensor_map]]
        extraTemp1 = t_1
        extraTemp2 = t_2
        extraTemp3 = t_3
        extraTemp4 = t_4
        extraTemp5 = t_5
        extraTemp6 = t_6
        extraTemp7 = t_7
        extraTemp8 = t_8
        extraHumid1 = h_1
        extraHumid2 = h_2
        extraHumid3 = h_3
        extraHumid4 = h_4
        extraHumid5 = h_5
        extraHumid6 = h_6
        extraHumid7 = h_7
        extraHumid8 = h_8
"""

    def modify_config(self, config_dict):
        print """
Changing the schema to include extraTemp and extraHumid colums """
        config_dict['DataBindings']['wx_binding']['schema'] = 'user.ws3000db.schema_for_ws3000'


#
# *******************************************************************
#
# define a main entry point for basic testing of the station.
# Invoke this as follows from the weewx root dir:
#
# PYTHONPATH=bin python bin/user/ws3000.py

if __name__ == '__main__':

    import optparse

    usage = """%prog [options] [--debug] [--help]"""

    syslog.openlog('ws3000', syslog.LOG_PID | syslog.LOG_CONS)
    syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_INFO))
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('--version', action='store_true',
                      help='display driver version')
    parser.add_option('--debug', action='store_true',
                      help='display diagnostic information while running')
    parser.add_option('--test', default='station',
                      help='what to test: station or driver')
    (options, args) = parser.parse_args()

    if options.version:
        print "driver version %s" % DRIVER_VERSION
        exit(1)

    if options.debug:
        syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_DEBUG))

    if options.test == 'driver':
        driver = WS3000()
        try:
            for p in driver.genLoopPackets():
                print p
        finally:
            driver.closePort()
    else:
        station = WS3000()
        while True:
            command = station.COMMANDS["sensor_values"]
            raw = station._getRawData(command)
            data = station._rawToData(raw, command)
            logdbg('data: %s' % data)
            packet = station._dataToWXPacket(data)
            logdbg('packet: %s' % packet)
            station.loop_interval
import schemas.wview

#
# *******************************************************************
#
# Changes to the database schema to take up to 8 sensors into account
schema_for_ws3000 = schemas.wview.schema + [('extraTemp4', 'REAL'),
                                            ('extraTemp5', 'REAL'),
                                            ('extraTemp6', 'REAL'),
                                            ('extraTemp7', 'REAL'),
                                            ('extraTemp8', 'REAL'),
                                            ('extraHumid3', 'REAL'),
                                            ('extraHumid4', 'REAL'),
                                            ('extraHumid5', 'REAL'),
                                            ('extraHumid6', 'REAL'),
                                            ('extraHumid7', 'REAL'),
                                            ('extraHumid8', 'REAL')]
# WEEWX CONFIGURATION FILE
#
# Copyright (c) 2009-2015 Tom Keffer <[email protected]>
# See the file LICENSE.txt for your rights.

##############################################################################

# This section is for general configuration information.

# Set to 1 for extra debug info, otherwise comment it out or set to zero
debug = 1

# Root directory of the weewx data file hierarchy for this station
WEEWX_ROOT = /home/halol/tmp/weewx

# How long to wait before timing out a socket (FTP, HTTP) connection
socket_timeout = 20

# Do not modify this. It is used when installing and updating weewx.
version = 3.8.0

##############################################################################

#   This section is for information about the station.

[Station]
    
    # Description of the station location
    location = Bar sur Loup
    
    # Latitude and longitude in decimal degrees
    latitude = 90.000
    longitude = 0.000
    
    # Altitude of the station, with unit it is in. This is downloaded from
    # from the station if the hardware supports it.
    altitude = 0, meter    # Choose 'foot' or 'meter' for unit
    
    # Set to type of station hardware. There must be a corresponding stanza
    # in this file with a 'driver' parameter indicating the driver to be used.
    #station_type = WS3000
    station_type = Simulator
    
    # If you have a website, you may specify an URL
    #station_url = http://www.example.com
    
    # The start of the rain year (1=January; 10=October, etc.). This is
    # downloaded from the station if the hardware supports it.
    rain_year_start = 1
    
    # Start of week (0=Monday, 6=Sunday)
    week_start = 0

##############################################################################

[Simulator]
    # This section is for the weewx weather station simulator
    
    # The time (in seconds) between LOOP packets.
    loop_interval = 2.5
    
    # The simulator mode can be either 'simulator' or 'generator'.
    # Real-time simulator. Sleep between each LOOP packet.
    mode = simulator
    # Generator.  Emit LOOP packets as fast as possible (useful for testing).
    #mode = generator
   
    units = METRICWX
 
    # The start time. Format is YYYY-mm-ddTHH:MM. If not specified, the default 
    # is to use the present time.
    #start = 2011-01-01T00:00
    
    # The driver to use:
    driver = weewx.drivers.simulator

##############################################################################

#   This section is for uploading data to Internet sites

[StdRESTful]
    
    [[StationRegistry]]
        # To register this weather station with weewx, set this to true
        register_this_station = false
    
    [[AWEKAS]]
        # This section is for configuring posts to AWEKAS.
        
        # If you wish to do this, set the option 'enable' to true,
        # and specify a username and password.
        enable = false
        username = replace_me
        # To guard against parsing errors, put your password in quotes:
        password = replace_me
    
    [[CWOP]]
        # This section is for configuring posts to CWOP.
        
        # If you wish to do this, set the option 'enable' to true,
        # and specify the station ID (e.g., CW1234).
        enable = false
        station = replace_me
    
    # If this is an APRS (radio amateur) station, uncomment
    # the following and replace with a passcode (e.g., 12345).
    #passcode = replace_me (APRS stations only)
    
    [[PWSweather]]
        # This section is for configuring posts to PWSweather.com.
        
        # If you wish to do this, set the option 'enable' to true,
        # and specify a station and password.
        enable = false
        station = replace_me
        # To guard against parsing errors, put your password in quotes:
        password = replace_me
    
    [[WOW]]
        # This section is for configuring posts to WOW.
        
        # If you wish to do this, set the option 'enable' to true,
        # and specify a station and password.
        enable = false
        station = replace_me
        # To guard against parsing errors, put your password in quotes:
        password = replace_me
    
    [[Wunderground]]
        # This section is for configuring posts to the Weather Underground.
        
        # If you wish to do this, set the option 'enable' to true,
        # and specify a station (e.g., 'KORHOODR3') and password.
        enable = false
        station = replace_me
        # To guard against parsing errors, put your password in quotes:
        password = replace_me
        
        # Set the following to True to have weewx use the WU "Rapidfire"
        # protocol. Not all hardware can support it. See the User's Guide.
        rapidfire = False

##############################################################################

#   This section specifies what reports, using which skins, to generate.

[StdReport]
    
    # Where the skins reside, relative to WEEWX_ROOT
    SKIN_ROOT = skins
    
    # Where the generated reports should go, relative to WEEWX_ROOT
    HTML_ROOT = public_html
    
    # The database binding indicates which data should be used in reports.
    data_binding = wx_binding
    
    # Each of the following subsections defines a report that will be run.
    
    [[StandardReport]]
        # See the customizing guide to change the units, plot types and line
        # colors, modify the fonts, display additional sensor data, and other
        # customizations. Many of those changes can be made here by overriding
        # parameters, or by modifying templates within the skin itself.
        
        # The StandardReport uses the 'Standard' skin, which contains the
        # images, templates and plots for the report.
        skin = Standard
        [[[Units]]]
            [[[[Groups]]]]
                group_altitude = meter
                group_speed2 = meter_per_second2
                group_pressure = mbar
                group_rain = mm
                group_rainrate = mm_per_hour
                group_temperature = degree_C
                group_degree_day = degree_C_day
                group_speed = meter_per_second
    
    [[FTP]]
        # FTP'ing the results to a webserver is treated as just another report,
        # albeit one with an unusual report generator!
        skin = Ftp
        
        # If you wish to use FTP, uncomment and fill out the next four lines.
        #user = replace with the ftp username
        #password = replace with the ftp password; put in quotes to guard 
against parsing errors.
        #server = replace with the ftp server name, e.g, www.threefools.org
        #path = replace with the ftp destination directory (e.g., /weather)
        
        # Set to True for an FTP over TLS (FTPS) connection. Not all servers
        # support this.
        secure_ftp = False
        
        # To upload files from something other than what HTML_ROOT is set
        # to above, specify a different HTML_ROOT here.
        #HTML_ROOT = public_html
        
        # Most FTP servers use port 21
        port = 21
        
        # Set to 1 to use passive mode, zero for active mode
        passive = 1
    
    [[RSYNC]]
        # rsync'ing to a webserver is treated as just another report
        skin = Rsync
        
        # If you wish to use rsync, you must configure passwordless ssh using
        # public/private key authentication from the user account that weewx
        # runs as to the user account on the remote machine where the files
        # will be copied.
        #
        # The following three lines determine where files will be sent.
        #server = replace with the rsync server name, e.g, www.threefools.org
        #path = replace with the rsync destination directory (e.g., /weather)
        #user = replace with the rsync username
        
        # Rsync can be configured to remove files from the remote server if
        # they don't exist under HTML_ROOT locally. USE WITH CAUTION: if you
        # make a mistake in the remote path, you could could unintentionally
        # cause unrelated files to be deleted. Set to 1 to enable remote file
        # deletion, zero to allow files to accumulate remotely.
        delete = 0

##############################################################################

#   This service acts as a filter, converting the unit system coming from
#   the hardware to a unit system in the database.

[StdConvert]
    
    # The target_unit affects only the unit system in the database. Once
    # chosen it cannot be changed without converting the entire database.
    # Modification of target_unit after starting weewx will result in
    # corrupt data - the database will contain a mix of US and METRIC data.
    #
    # The value of target_unit does not affect the unit system for
    # reporting - reports can display US, Metric, or any combination of units.
    #
    # In most cases, target_unit should be left as the default: US
    #
    # In particular, those migrating from a standard wview installation
    # should use US since that is what the wview database contains.
    
    # DO NOT MODIFY THIS VALUE UNLESS YOU KNOW WHAT YOU ARE DOING!
    target_unit = US    # Options are 'US', 'METRICWX', or 'METRIC'

##############################################################################

#   This section can adjust data using calibration expressions.

[StdCalibrate]
    
    [[Corrections]]
        # For each type, an arbitrary calibration expression can be given. 
        # It should be in the units defined in the StdConvert section.
        # Example:
        foo = foo + 0.2

##############################################################################

#   This section is for quality control checks. If units are not specified,
#   values must be in the units defined in the StdConvert section.

[StdQC]
    
    [[MinMax]]
        barometer = 26, 32.5, inHg
        outTemp = -40, 120, degree_F
        inTemp = 10, 120, degree_F
        outHumidity = 0, 100
        inHumidity = 0, 100
        windSpeed = 0, 120, mile_per_hour
        pressure = 24, 34.5, inHg

##############################################################################

#   This section controls the origin of derived values.

[StdWXCalculate]
    
    [[Calculations]]
        # Derived quantities are calculated by this service. Possible values 
are:
        #  hardware        - use the value provided by hardware
        #  software        - use the value calculated by weewx
        #  prefer_hardware - use value provide by hardware if available,
        #                      otherwise use value calculated by weewx
        
        pressure = prefer_hardware
        barometer = prefer_hardware
        altimeter = prefer_hardware
        windchill = prefer_hardware
        heatindex = prefer_hardware
        dewpoint = prefer_hardware
        inDewpoint = prefer_hardware
        rainRate = hardware

##############################################################################

#   For hardware that supports it, this section controls how often the
#   onboard clock gets updated.

[StdTimeSynch]
    
    # How often to check the weather station clock for drift (in seconds)
    clock_check = 14400
    
    # How much it can drift before we will correct it (in seconds)
    max_drift = 5

##############################################################################

#   This section is for configuring the archive service.

[StdArchive]
    
    # If the station hardware supports data logging then the archive interval
    # will be downloaded from the station. Otherwise, specify it (in seconds).
    archive_interval = 60
    
    # If possible, new archive records are downloaded from the station
    # hardware. If the hardware does not support this, then new archive
    # records will be generated in software.
    # Set the following to "software" to force software record generation.
    record_generation = hardware
    
    # Whether to include LOOP data in hi/low statistics
    loop_hilo = True
    
    # The data binding used to save archive records
    data_binding = wx_binding

##############################################################################

#   This section binds a data store to a database.

[DataBindings]
    
    [[wx_binding]]
        # The database must match one of the sections in [Databases].
        # This is likely to be the only option you would want to change.
        database = archive_sqlite
        # The name of the table within the database
        table_name = archive
        # The manager handles aggregation of data for historical summaries
        manager = weewx.wxmanager.WXDaySummaryManager
        # The schema defines the structure of the database.
        # It is *only* used when the database is created.
        schema = user.ws3000db.schema_for_ws3000

##############################################################################

#   This section defines various databases.

[Databases]
    
    # A SQLite database is simply a single file
    [[archive_sqlite]]
        database_type = SQLite
        database_name = weewx.sdb
    
    # MySQL
    [[archive_mysql]]
        database_type = MySQL
        database_name = weewx

##############################################################################

#   This section defines defaults for the different types of databases.

[DatabaseTypes]
    
    # Defaults for SQLite databases
    [[SQLite]]
        driver = weedb.sqlite
        # Directory in which the database files are located
        SQLITE_ROOT = %(WEEWX_ROOT)s/archive
    
    # Defaults for MySQL databases
    [[MySQL]]
        driver = weedb.mysql
        # The host where the database is located
        host = localhost
        # The user name for logging in to the host
        user = weewx
        # The password for the user name. Put in quotes to guard against 
parsing errors.
        password = weewx

##############################################################################

#   This section configures the internal weewx engine.

[Engine]
    
    [[Services]]
        # This section specifies the services that should be run. They are
        # grouped by type, and the order of services within each group
        # determines the order in which the services will be run.
        prep_services = weewx.engine.StdTimeSynch
        data_services = user.add_ws3000_data.AddWS300Data
        process_services = weewx.engine.StdConvert, weewx.engine.StdCalibrate, 
weewx.engine.StdQC, weewx.wxservices.StdWXCalculate
        archive_services = weewx.engine.StdArchive
        restful_services = weewx.restx.StdStationRegistry, 
weewx.restx.StdWunderground, weewx.restx.StdPWSweather, weewx.restx.StdCWOP, 
weewx.restx.StdWOW, weewx.restx.StdAWEKAS
        report_services = weewx.engine.StdPrint, weewx.engine.StdReport

##############################################################################

[WS3000]
    # This section is for the Ambient Weather WS3000
    
    # The driver to use
    driver = user.ws3000
    
    # The station model, e.g., WS3000, WS3000-X3, WS3000-X5 (all the same...)
    model = WS3000
    
    # [Optional] The interval at which loop packets should be generated by the 
driver
    # Default is 10
    #loop_interval = 15
    
    # [Optional] USB vendor ID and product ID, as returned by lsusb. Only 
required if the device
    # cannot be found with the default values
    # Defaults are 0x0483 and 0x5750
    vendor_id = 0x0483
    product_id = 0x5750
    
    # [Optional] By default, all the sensor values are stored in the extraTemp 
or extraHumid columns. The assumption here is
    # that the WS3000 is used as a secondary station to enhance another 
existing station with additional 
    # temperature sensors, and that the usual inTemp, outTemp, etc. are already 
used by the primary station.
    # NOTE: of course, the database schema must be modified to include the 
missing columns.
    [[sensor_map]]
        extraTemp1 = t_1
        extraTemp2 = t_2
        extraTemp3 = t_3
        extraTemp4 = t_4
        extraTemp5 = t_5
        extraTemp6 = t_6
        extraTemp7 = t_7
        extraTemp8 = t_8
        extraHumid1 = h_1
        extraHumid2 = h_2
        extraHumid3 = h_3
        extraHumid4 = h_4
        extraHumid5 = h_5
        extraHumid6 = h_6
        extraHumid7 = h_7
        extraHumid8 = h_8

##############################################################################

Reply via email to