Hi George,

Yes I did manage to get it working!
I ended up just editing the driver and configuration files where they are 
located.

I installed all of the following libraries:
sudo pip3 install Adafruit-Blinka
sudo pip3 install adafruit-circuitpython-bme280
sudo pip3 install adafruit-circuitpython-ads1x15
sudo apt-get install python3-w1thermsensor

Change file located in  /usr/share/weewx/user/BCRobotics.py to what I have 
attached
Add the BCRobotics section to the weewx.conf file located in /etc/weewx
Attached is my config file for reference but it has some location specific 
information that you'll need to change.

I reran config and it works!


Let me know how you make out or if you have any questions.

Note for any experts: I tried to run the install.py with the modified 
driver file but got a "module setup not found"
Thought it may be a Python version issue but couldn't determine the Python3 
equivalent. Appreciate any hints.
Maybe later I will add my changes to Github but thats a whole other 
learning session.  

Terry
On Thursday, 18 February 2021 at 06:21:04 UTC-8 [email protected] wrote:

> Hi Terry,
>
> I'm trying to do exactly the same thing.
>
> Did you have any luck with the driver?
>
> Thanks in advance.
>
> George
>
> On Wednesday, February 17, 2021 at 5:19:02 PM UTC+2 [email protected] 
> wrote:
>
>> Can I just modify the code of the already installed driver or would I 
>> need to repackage and reinstall it. I may do that later but its another 
>> piece I need to learn.
>>
>> Also how do I ensure its all running Python3?
>>
>> Thanks for all the help.
>>
>> Terry
>>
>> On Tuesday, 16 February 2021 at 18:45:15 UTC-8 [email protected] wrote:
>>
>>> Driver looks like it's written for Python2 (the give away to me is the 
>>> print statement on the last line), so you might have a bit of fun fixing 
>>> python2/python3 issues. Not too terribly difficult. If you could get the 
>>> test program to work, you can probably get the driver to work too.
>>>
>>> On Tue, Feb 16, 2021 at 5:46 PM Terry Steneker <[email protected]> 
>>> wrote:
>>>
>>>> I am using the driver located here: 
>>>> https://github.com/David-Enst/WeeWX-BCRobotics
>>>>
>>>> I am also attaching the file
>>>>
>>>>
>>>>
>>>> On Tuesday, 16 February 2021 at 16:53:24 UTC-8 [email protected] 
>>>> wrote:
>>>>
>>>>> What driver are you using?
>>>>> It's going to be really tough to help with this because you have 
>>>>> unique hardware and aren't asking a very answerable question. 
>>>>>
>>>>> On Tue, Feb 16, 2021 at 3:26 PM Terry Steneker <[email protected]> 
>>>>> wrote:
>>>>>
>>>>>>
>>>>>> I just purchased the BCRobotics board and tried to install the 
>>>>>> required software for it. I ran into problems when I tried to test the 
>>>>>> BME280 using the Adafruit ADS1x15 library. Kept getting errors and the 
>>>>>> python Adafruit_BME280 library is deprecated. 
>>>>>>
>>>>>> Instead of trying to fix the errors I went the hard way and upgraded 
>>>>>> to the adafruit-circuitpython libraries so I can also run Python3
>>>>>>
>>>>>> sudo pip3 install adafruit-circuitpython-bme280
>>>>>>
>>>>>> sudo pip3 install adafruit-circuitpython-ads1x15
>>>>>>
>>>>>> I then modified the BCRobotics-test-app.py to run under Python3 and 
>>>>>> the upgraded Adafruit libraries.
>>>>>> Tested the program and it works!
>>>>>>
>>>>>> I have attached the modified program.
>>>>>>
>>>>>> I need to modify the driver to work the same as the updated code but 
>>>>>> not sure how to do that. Can I just substitute the same modifications 
>>>>>> that 
>>>>>> I made to the test program? 
>>>>>>
>>>>>> Thanks
>>>>>> Terry
>>>>>>
>>>>>> On Sunday, 24 November 2019 at 10:25:09 UTC-8 [email protected] 
>>>>>> wrote:
>>>>>>
>>>>>>> Louis,
>>>>>>>
>>>>>>> thank you very much for your reply.
>>>>>>>
>>>>>>> I didn't realize they first did it with Python 2.7. I though you 
>>>>>>> used it in order for it to work with the interceptor driver.
>>>>>>>
>>>>>>> I'll keep using python 2.7 and your code but it seems that I'm 
>>>>>>> missing some libraries.
>>>>>>>
>>>>>>> (I think I had them all but I keep getting a " BME280_OSAMPLE_8' is 
>>>>>>> not defined " etc. errors) 
>>>>>>>
>>>>>>> I'll try and find the original code and libraries for Python 2.7 and 
>>>>>>> do the necessary adjustments.
>>>>>>>
>>>>>>> Thanks again!
>>>>>>>
>>>>>>> On Sun, Nov 24, 2019 at 7:15 PM Louis De Lange <[email protected]> 
>>>>>>> wrote:
>>>>>>>
>>>>>>>> George,
>>>>>>>>
>>>>>>>> At the time when I completed that project the tutorial on the 
>>>>>>>> BC-Robotics website was written in Python 2.7 so I used all the 2.7 
>>>>>>>> libraries in my code.  With some research you should be able to 
>>>>>>>> convert the 
>>>>>>>> original code to work with python 3 libraries.
>>>>>>>>
>>>>>>>> Sorry, I have not updated anything because if it works why break it.
>>>>>>>>
>>>>>>>> LDL
>>>>>>>>
>>>>>>>> On Saturday, 23 November 2019 13:06:57 UTC-8, George Nimrodel wrote:
>>>>>>>>>
>>>>>>>>> Hey Louis,
>>>>>>>>>
>>>>>>>>> I'm trying to do exactly what you've done with the difference that 
>>>>>>>>> I have weewx running on the RPi and I'm using only the BME280 for 
>>>>>>>>> temperature in a separate enclosure.
>>>>>>>>>
>>>>>>>>> I'm having a bit of a trouble with your code. I keep getting 
>>>>>>>>> errors regarding the libraries.
>>>>>>>>>
>>>>>>>>> I've noticed that you are not using the python 3 libraries from 
>>>>>>>>> the tutorial.
>>>>>>>>>
>>>>>>>>> I would appreciate it if you could tell me which steps you took 
>>>>>>>>> that are not included in the tutorial in order for your code to work.
>>>>>>>>>
>>>>>>>>> Any other pointers would also be appreciated
>>>>>>>>>
>>>>>>>>> Thank in advance!
>>>>>>>>>
>>>>>>>>> On Wednesday, December 12, 2018 at 5:53:25 AM UTC+2, Louis De 
>>>>>>>>> Lange wrote:
>>>>>>>>>>
>>>>>>>>>> I recently came across a really excellent solution for putting 
>>>>>>>>>> together your own weather station on the cheap with high quality 
>>>>>>>>>> sensors - 
>>>>>>>>>> and most importantly a very useful weather HAT to use with a 
>>>>>>>>>> Raspberry PI 
>>>>>>>>>> to connect all the sensors.
>>>>>>>>>>
>>>>>>>>>> It comes complete with a 4 part step by step tutorial to assemble 
>>>>>>>>>> the whole station, and basic code to upload the data to and online 
>>>>>>>>>> service 
>>>>>>>>>> - see link below:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-1/
>>>>>>>>>>
>>>>>>>>>> I completed my own installation based on the instructions in the 
>>>>>>>>>> tutorial and my station running on weewx is active at the link below
>>>>>>>>>>
>>>>>>>>>> http://peachlandweather.ca/mystation/
>>>>>>>>>>
>>>>>>>>>> For the outdoor portion I used a Raspberry Pi Zero W, with the 
>>>>>>>>>> weather HAT.  Weewx is running indoors in a FreeBSD jail, using a 
>>>>>>>>>> stock 
>>>>>>>>>> Interceptor driver.  I modified the basic upload code provided in 
>>>>>>>>>> the 
>>>>>>>>>> tutorial quite extensively to generate upload loops that matched the 
>>>>>>>>>> Observer URLs supported by the Interceptor driver, and also to 
>>>>>>>>>> produce 
>>>>>>>>>> derived observations not included in the original code.
>>>>>>>>>>
>>>>>>>>>> The upload code is attached for anyone who might be interested in 
>>>>>>>>>> trying to assemble their own.
>>>>>>>>>>
>>>>>>>>>> I   tested the results from using the station against my Vantage 
>>>>>>>>>> Pro 2 and so far it seems to be pretty close - for less than 20% of 
>>>>>>>>>> the 
>>>>>>>>>> cost of a Vantage Pro.
>>>>>>>>>>
>>>>>>>>> -- 
>>>>>>>> You received this message because you are subscribed to a topic in 
>>>>>>>> the Google Groups "weewx-user" group.
>>>>>>>> To unsubscribe from this topic, visit 
>>>>>>>> https://groups.google.com/d/topic/weewx-user/udZCCCJlNE8/unsubscribe
>>>>>>>> .
>>>>>>>> To unsubscribe from this group and all its topics, send an email to 
>>>>>>>> [email protected].
>>>>>>>> To view this discussion on the web visit 
>>>>>>>> https://groups.google.com/d/msgid/weewx-user/db1a607e-3fb0-4ed1-974e-0930406e7e6a%40googlegroups.com
>>>>>>>>  
>>>>>>>> <https://groups.google.com/d/msgid/weewx-user/db1a607e-3fb0-4ed1-974e-0930406e7e6a%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>> .
>>>>>>>>
>>>>>>> -- 
>>>>>>
>>>>> 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].
>>>>>> To view this discussion on the web visit 
>>>>>> https://groups.google.com/d/msgid/weewx-user/3ddea820-bf91-44ff-9a93-90a3214241c3n%40googlegroups.com
>>>>>>  
>>>>>> <https://groups.google.com/d/msgid/weewx-user/3ddea820-bf91-44ff-9a93-90a3214241c3n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>> .
>>>>>>
>>>>>
>>>>>
>>>>> -- 
>>>>> Peter Quinn
>>>>> (415)794-2264 <(415)%20794-2264>
>>>>>
>>>> -- 
>>>> 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].
>>>>
>>> To view this discussion on the web visit 
>>>> https://groups.google.com/d/msgid/weewx-user/95c558e3-8772-492e-a9e1-7fbdebf6dd97n%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/weewx-user/95c558e3-8772-492e-a9e1-7fbdebf6dd97n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>>
>>>
>>> -- 
>>> Peter Quinn
>>> (415)794-2264 <(415)%20794-2264>
>>>
>>

-- 
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].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/weewx-user/78364c1c-eb33-4263-9c86-860ef98978aen%40googlegroups.com.
# WEEWX CONFIGURATION FILE
#
# Copyright (c) 2009-2021 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 = 0

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

# Whether to log successful operations
log_success = True

# Whether to log unsuccessful operations
log_failure = True

# 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 = 4.4.0

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

#   This section is for information about the station.

[Station]
    
    # Description of the station location
    location = Rail Lake
    
    # Latitude in decimal degrees. Negative for southern hemisphere
    latitude = 51.951
    # Longitude in decimal degrees. Negative for western hemisphere.
    longitude = -121.484
    
    # Altitude of the station, with unit it is in. This is downloaded from
    # from the station if the hardware supports it.
    altitude = 1095, meter
    
    # 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 = BCRobotics
    
    # 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 = 6

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

[BCRobotics]
    # This section is for the "Spark Fun" SEN-08942 / BC Robotics weather 
stations.
    # See: https://www.sparkfun.com/products/8942
    #      
https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-1/
    
    # The time (in seconds) between LOOP packets. Default is:
    loop_interval = 3
    
    # Driver mode - tcp, udp, or serial
    mode = serial
    
    # If serial, specify the serial port device. (ex. /dev/ttyS0, /dev/ttyUSB0,
    # or /dev/cuaU0)
    # If TCP, specify the IP address and port number. (ex. 192.168.36.25:3000)
    port = /dev/ttyS0
    
    # The amount of time, in seconds, before the connection fails if there is
    # no response
    timeout = 3
    
    # Debug level - the level of message logging. The higher
    # the number, the more info is logged.
    debug_read = 0
    
    # The driver to use:
    driver = user.BCRobotics

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

[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
    
    # 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.
        # To guard against parsing errors, put the password in quotes.
        enable = false
        username = replace_me
        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.
        # To guard against parsing errors, put the password in quotes.
        enable = false
        station = replace_me
        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.
        # To guard against parsing errors, put the password in quotes.
        enable = false
        station = replace_me
        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.
        # To guard against parsing errors, put the password in quotes.
        enable = false
        station = replace_me
        password = replace_me
        
        # If you plan on using wunderfixer, set the following
        # to your API key:
        api_key = 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 = /etc/weewx/skins
    
    # Where the generated reports should go, relative to WEEWX_ROOT
    HTML_ROOT = /var/www/html/weewx
    
    # The database binding indicates which data should be used in reports.
    data_binding = wx_binding
    
    # Whether to log a successful operation
    log_success = True
    
    # Whether to log an unsuccessful operation
    log_failure = True
    
    # Each of the following subsections defines a report that will be run.
    # 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.
    
    [[SeasonsReport]]
        # The SeasonsReport uses the 'Seasons' skin, which contains the
        # images, templates and plots for the report.
        skin = Seasons
        enable = true
    
    [[SmartphoneReport]]
        # The SmartphoneReport uses the 'Smartphone' skin, and the images and
        # files are placed in a dedicated subdirectory.
        skin = Smartphone
        enable = false
        HTML_ROOT = /var/www/html/weewx/smartphone
    
    [[MobileReport]]
        # The MobileReport uses the 'Mobile' skin, and the images and files
        # are placed in a dedicated subdirectory.
        skin = Mobile
        enable = false
        HTML_ROOT = /var/www/html/weewx/mobile
    
    [[StandardReport]]
        # This is the old "Standard" skin. By default, it is not enabled.
        skin = Standard
        enable = false
        [[[Units]]]
            [[[[Groups]]]]
                group_altitude = meter
                group_speed = km_per_hour
                group_speed2 = km_per_hour2
                group_pressure = hPa
                group_rain = mm
                group_rainrate = mm_per_hour
                group_temperature = degree_C
                group_degree_day = degree_C
    
    [[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, set "enable" to "true", then
        # fill out the next four lines.
        # Use quotes around passwords to guard against parsing errors.
        enable = false
        user = replace_me
        password = replace_me
        server = replace_me    # The ftp server name, e.g, www.myserver.org
        path = replace_me    # The 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 = /var/www/html/weewx
        
        # 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 to the user account on the remote machine where the files
        # will be copied.
        #
        # If you wish to use rsync, set "enable" to "true", then
        # fill out server, user, and path.
        # The server should appear in your .ssh/config file.
        # The user is the username used in the identity file.
        # The path is the destination directory, such as /var/www/html/weather.
        # Be sure that the user has write permissions on the destination!
        enable = false
        server = replace_me
        user = replace_me
        path = replace_me
        
        # To upload files from something other than what HTML_ROOT is set
        # to above, specify a different HTML_ROOT here.
        #HTML_ROOT = /var/www/html/weewx
        
        # 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
    
    ####
    
    # Various options for customizing your reports.
    
    [[Defaults]]
        
        [[[Units]]]
            
            # The following section sets what unit to use for each unit group.
            # NB: The unit is always in the singular. I.e., 'mile_per_hour',
            # NOT 'miles_per_hour'
            [[[[Groups]]]]
                
                group_altitude = meter    # Options are 'foot' or 'meter'
                group_degree_day = degree_C_day    # Options are 'degree_F_day' 
or 'degree_C_day'
                group_distance = km    # Options are 'mile' or 'km'
                group_pressure = mbar    # Options are 'inHg', 'mmHg', 'mbar', 
'hPa', or 'kPa'
                group_rain = mm    # Options are 'inch', 'cm', or 'mm'
                group_rainrate = mm_per_hour    # Options are 'inch_per_hour', 
'cm_per_hour', or 'mm_per_hour'
                group_speed = meter_per_second    # Options are 
'mile_per_hour', 'km_per_hour', 'knot', or 'meter_per_second'
                group_speed2 = meter_per_second2    # Options are 
'mile_per_hour2', 'km_per_hour2', 'knot2', or 'meter_per_second2'
                group_temperature = degree_C    # Options are 'degree_F' or 
'degree_C'
            
            # The following section sets the formatting for each type of unit.
            [[[[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 = %.1f
                km_per_hour = %.0f
                km_per_hour2 = %.1f
                knot = %.0f
                knot2 = %.1f
                kPa = %.2f
                mbar = %.1f
                meter = %.0f
                meter_per_second = %.1f
                meter_per_second2 = %.1f
                mile = %.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"
            
            # The following section overrides the label used for each type of 
unit
            [[[[Labels]]]]
                
                meter = " meter", " meters"    # You may prefer "metre".
                day = " day", " days"
                hour = " hour", " hours"
                minute = " minute", " minutes"
                second = " second", " seconds"
                NONE = ""
            
            # The following section sets the format for each time scale.
            # The values below will work in every locale, but they may not look
            # particularly attractive.
            [[[[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]]]]
                
                # Ordinal directions. The last one is for no wind direction
                directions = N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, 
W, WNW, NW, NNW, N/A
            
            # The following section sets the base temperatures used for the
            #  calculation of heating, cooling, and growing degree-days.
            [[[[DegreeDays]]]]
                
                # Base temperature for heating days, with unit:
                heating_base = 65, degree_F
                # Base temperature for cooling days, with unit:
                cooling_base = 65, degree_F
                # Base temperature for growing days, with unit:
                growing_base = 50, degree_F
            
            # A trend takes a difference across a time period. The following
            # section sets the time period, and how big an error is allowed to
            # still be counted as the start or end of a period.
            [[[[Trend]]]]
                
                time_delta = 10800    # 3 hours
                time_grace = 300    # 5 minutes
        
        # The labels to be used for each observation type
        [[[Labels]]]
            
            # Set to hemisphere abbreviations suitable for your location:
            hemispheres = N, S, E, W
            
            # Formats to be used for latitude whole degrees, longitude whole
            # degrees, and minutes:
            latlon_formats = %02d, %03d, %05.2f
            
            # Generic labels, keyed by an observation type.
            [[[[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
                
                # Sensor status indicators
                
                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]]]
            
            # The labels to be used for the phases of the moon:
            moon_phases = New, Waxing crescent, First quarter, Waxing gibbous, 
Full, Waning gibbous, Last quarter, Waning crescent

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

#   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
        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

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

#   This section controls the origin of derived values.

[StdWXCalculate]
    
    [[Calculations]]
        # How to calculate derived quantities.  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
        altimeter = prefer_hardware
        appTemp = prefer_hardware
        barometer = prefer_hardware
        cloudbase = prefer_hardware
        dewpoint = prefer_hardware
        ET = prefer_hardware
        heatindex = prefer_hardware
        humidex = prefer_hardware
        inDewpoint = prefer_hardware
        maxSolarRad = prefer_hardware
        rainRate = prefer_hardware
        windchill = prefer_hardware
        windrun = prefer_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 = 300
    
    # 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.manager.DaySummaryManager
        # The schema defines the structure of the database.
        # It is *only* used when the database is created.
        schema = schemas.wview_extended.schema

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

#   This section defines various databases.

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

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

#   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 = /var/lib/weewx
    
    # 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 (quotes guard against parsing errors)
        password = weewx

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

#   This section configures the internal weewx engine.

[Engine]
    
    # The following section specifies which services should be run and in what 
order.
    [[Services]]
        prep_services = weewx.engine.StdTimeSynch
        data_services = ,
        process_services = weewx.engine.StdConvert, weewx.engine.StdCalibrate, 
weewx.engine.StdQC, weewx.wxservices.StdWXCalculate
        xtype_services = weewx.wxxtypes.StdWXXTypes, 
weewx.wxxtypes.StdPressureCooker, weewx.wxxtypes.StdRainRater, 
weewx.wxxtypes.StdDelta
        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
# Copyright 2019 David W. Enstrom, all rights reserved
# Distributed under the terms of the GNU Public License (GPLv3)
"""
Driver to collect data from the "Spark Fun" SEN-08942 RoHS
weather meters and the BC Robotics interface.

See:    https://www.sparkfun.com/products/8942 
        https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-1/

"""

import syslog
import threading
import time
import math
import board
import busio
import adafruit_bme280
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
from w1thermsensor import W1ThermSensor
import RPi.GPIO as GPIO

import weewx.drivers
import weewx.units
import weewx.accum

DRIVER_NAME = 'BCRobotics'
DRIVER_VERSION = '1.0.24'

windTick = 0     # Count of the wind speed input trigger
rainTick = 0     # Count of the rain input trigger
interval = 3     # Set now to define scope of variable
rainTime = 0     # Use this to detect erroneous rain events
out_Temp = 0     # Set now to define scope for rain check

try:
     ds18b20 = W1ThermSensor()
except Exception as err:
     loginf('Error setting up Temperature Sensor %s' % err)
     TempSensor = False
else:
     TempSensor = True

i2c = busio.I2C(board.SCL, board.SDA)
bme = adafruit_bme280.Adafruit_BME280_I2C(i2c)
ads = ADS.ADS1115(i2c, gain=1)
chan = AnalogIn(ads, ADS.P0)


def loader(config_dict, _):
    return BCRoboDriver(**config_dict[DRIVER_NAME])

def confeditor_loader():
    return BCRoboConfEditor()

class BCRoboConfEditor(weewx.drivers.AbstractConfEditor):
    @property
    def default_stanza(self):
        return """

[BCRobotics]
    # This section is for the "Spark Fun" SEN-08942 / BC Robotics weather stations.
    # See: https://www.sparkfun.com/products/8942
    #      https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-1/

    # The time (in seconds) between LOOP packets. Default is:
    loop_interval = 3

    # Driver mode - tcp, udp, or serial
    mode = serial

    # If serial, specify the serial port device. (ex. /dev/ttyS0, /dev/ttyUSB0,
    # or /dev/cuaU0)
    # If TCP, specify the IP address and port number. (ex. 192.168.36.25:3000)
    port = /dev/ttyS0

    # The amount of time, in seconds, before the connection fails if there is
    # no response
    timeout = 3

    # Debug level - the level of message logging. The higher
    # the number, the more info is logged.
    debug_read = 0

    # The driver to use:
    driver = user.BCRobotics
    
"""

# flags for enabling/disabling debug verbosity
DEBUG_COMM = 0
DEBUG_CONFIG_DATA = 0
DEBUG_WEATHER_DATA = 0
DEBUG_HISTORY_DATA = 0
DEBUG_DUMP_FORMAT = 'auto'


def logmsg(dst, msg):
    syslog.syslog(dst, 'BCRobo: %s: %s' %
                  (threading.currentThread().getName(), msg))
    
def logdbg(msg):
    logmsg(syslog.LOG_DEBUG, msg)


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


def logcrt(msg):
    logmsg(syslog.LOG_CRIT, msg)


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


def logtee(msg):
    loginf(msg)
    print ("%s\r" % msg)


class BCRoboDriver(weewx.drivers.AbstractDevice):
    """weewx driver that communicates with a "Spark Fun" SEN-08942 / BC Robotics station

    mode - Communication mode - TCP, UDP, or Serial.
    [Required. Default is serial] 
    
    port - Serial port or network address.
    [Required. Default is /dev/ttyS0 for serial,
     and 192.168.36.25:3000 for TCP/IP]

    loop_interval - The time (in seconds) between LOOP packets.
    [Required. Default is loop_interval = 3]
    
    timeout - The amount of time, in seconds, before the connection fails if
    there is no response.
    [Optional. Default is 3]

    debug_read - The level of message logging. The higher this number, the more
    information is logged.
    [Optional. Default is 0]
    
    """
    def __init__(self, **stn_dict):
         
         loginf('Driver version is %s' % DRIVER_VERSION)
         global interval
         interval = int(stn_dict.get('loop_interval', 3))
         #loginf('Interval is %s' % interval)
         global rainTime
         rainTime = int(time.time())   # used to detect erronious rain ticks

         try:
              # Set GPIO pins to use BCM pin numbers
              GPIO.setmode(GPIO.BCM)
              
              # Set digital pin 17 to an input and enable the pullup (wind speed)
              GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)

              # Set digital pin 23 to an input and enable the pullup (rain)
              GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)

              # Define event to detect wind (4 ticks per revolution)
              #  1 tick/sec = 1.492 mph or 2.4 km/h
              #  So: wind = (windTick * 2.4) / loop_interval
              GPIO.add_event_detect(17, GPIO.BOTH)
              def windtrig(self):
                  global windTick
                  windTick += 1
                
              GPIO.add_event_callback(17, windtrig)

              # Define event to detect rain (0.2794mm per tick)
              # with a 1hr time period where the first tick is ignored
              # which is used to detect an improper single tick
              GPIO.add_event_detect(23, GPIO.FALLING)
              def raintrig(self):
                  global rainTick
                  global rainTime
                  global out_Temp
                  if out_Temp <= 0:    # can't rain in the winter
                      loginf('Bad rain tick')
                  else:
                      if int(time.time())-rainTime >= 3600:
                          loginf('Possible bad rain tick')
                          rainTime = int(time.time())
                      else:
                          rainTime = int(time.time())
                          rainTick += 1
              
              GPIO.add_event_callback(23, raintrig)
              
         except Exception as err:
               loginf('Error setting up GPIO: ' % err)
         else:
               loginf('GPIO setup fine.')

    @property
    def hardware_name(self):
        return "BCRobotics"
    
    def genLoopPackets(self):
        while True:
            packet = {'dateTime': int(time.time() + 0.0),
                      'usUnits': weewx.METRIC}
            readings = StationData.get_readings()
            packet.update(readings)
    #        self._augment_packet(packet)
            yield packet

    #def _augment_packet(self, packet):
    #    # calculate the rain delta from rain total
    #    if self.last_rain is not None:
    #        packet['rain'] = packet['rain_total'] - self.last_rain
    #    else:
    #        packet['rain'] = None
    #    self.last_rain = packet['rain_total']

# ======================================================================= #
#       StationData class - setup stn and get data from the device        #
# ======================================================================= #


class StationData():
    def __init__(self):
       # Initialize the setup and define ports
       last_rain = None
       global windTick
       global rainTick
       windTick = 0   # Count of the wind speed input trigger
       rainTick = 0   # Count of the rain input trigger



    @staticmethod
    def get_readings():
        """ The "Spark Fun" SEN-08942 / BC Robotics station emits data
         through a BME280 interface, a ds18b20 temperature sensor plus
         a ADS1015 Analog to Digital chip for the wind direction.

        https://www.bc-robotics.com/tutorials/raspberry-pi-weather-station-part-2/

        The following data is provided by the sensor hardware:

          windSpeed    - from total ticks (1 tick/sec = 2.4 km/h)
          windDir      - wind direction (0-255)
          out_Temp     - outdoor temperature (in Deg C)
          rain         - rain during the loop_interval (1 tick = 0.2794 mm)
          pressure     - pressure (in Pascals)
          case_temp    - hardware case temperature (in Deg C)
          out_humidity - outdoor humidity (calculated, see below)
          in_humidity  - humidity inside the case (+/-0.1 %)
          
        """
        #
        # Get the readings, define the data list, and fill it in from readings
        # NOTE: The pressure reading is 'pressure', not 'barometer'
        #

        #if global TempSensor
        # Get temperature from DS18B20 sensor in degrees_C
        global out_Temp
        out_Temp = ds18b20.get_temperature()
        
        # Get Temperature from BME280 in degrees_C
        case_temp = bme.temperature
        
        # Get Barometric Pressure from BME280 in Pascals
        #   and convert to mbar
        #   100 pascal = 1 mbar, or 0.00029529983071445 inhg
        pressure = bme.pressure
        
        # Get Humidity (inside the case) from BME280 in %
        in_humidity = bme.humidity
        
        # This humidity is measured inside the case, which is warmer than the 
        # ambient air. Therefore it is converted to external humidity based
        # upon the case_temp, in_humidity, pressure, and out_Temp. 
        # 
        # Use NOAA formulae:
        VapPress = (6.112 * math.exp(17.67 * case_temp / (case_temp + 243.5))) * (in_humidity/100)
        DewPoint = (243.5 * math.log(VapPress / 6.112))/(17.67 - math.log(VapPress / 6.112))
        absVapPress = 6.11 * math.pow(10, (7.5 * DewPoint / (237.7 + DewPoint)))
        actMixRatio = 621.97 * absVapPress / (pressure - absVapPress)
        
        # Adjust humidity reading to the outside temperature
        # using NOAA values:
        out_humidity = actMixRatio * 10 / (0.42 * math.exp(out_Temp * 0.06235394))
        if out_humidity > 100:
            out_humidity = 100.0

        # Calculate wind direction (angle) based on ADC reading
        #   Read ADC channel 0 with a gain of 1
        windDir = 1.5

        val = chan.value

        if 19600 <= val <= 20999:
            windDir = 0

        if 9000 <= val <= 10799:
            windDir = 22.5

        if 10800 <= val <= 13999:
            windDir = 45

        if 2000 <= val <= 2299:
            windDir = 67.5

        if 2300 <= val <= 2999:
            windDir = 90

        if 1000 <= val <= 1999:
            windDir = 112.5

        if 4000 <= val <= 4999:
            windDir = 135

        if 3000 <= val <= 3999:
            windDir = 157.5

        if 6600 <= val <= 8999:
            windDir = 180

        if 5000 <= val <= 6599:
            windDir = 202.5

        if 15900 <= val <= 17499:
            windDir = 225

        if 14000 <= val <= 15899:
            windDir = 247.5

        if 24000 <= val <= 24999:
            windDir = 270

        if 21000 <= val <= 21999:
            windDir = 292.5

        if 22000 <= val <= 23999:
            windDir = 315

        if 17500 <= val <= 19599:
            windDir = 337.5

        if windDir == 1.5:
            value = str(val)
            loginf('Wind direction error: ' + value)


        # Calculate the average wind speed over this 'interval' (km/h)
        #  1 tick/sec = 1.492 mph or 2.4 km/h
        #  So: (windTick * 2.4) / loop_interval
        global windTick
        windSpeed = (windTick * 2.4) / interval
        windTick = 0

        # Calculate the rainfall over this 'interval' (cm)
        # 1 tick = 0.011 inches or 0.02794 cm 
        global rainTick
        rain = rainTick * 0.02794
        
        if rain > 0:
            raintxt = str(rain)
        #    loginf('Rain is falling: ' + raintxt)
            rainRate = (rain / interval) * 3600  # cm/h
            rainTick = 0
        else:
            rainRate = None
            rain = None 
            
        data = dict()
        data['windSpeed'] = windSpeed       # km/h
        data['windDir'] = windDir           # compass deg
        data['outTemp'] = out_Temp          # degree_C
        data['rain'] = rain                 # cm as per default
        data['rainRate'] = rainRate         # cm/hr
        data['pressure'] = pressure         # mbar
        data['inTemp'] = case_temp          # degree_C
        data['inHumidity'] = in_humidity    # percent
        data['outHumidity'] = out_humidity  # percent
        
        rain = 0
        rainRate = 0
        return data

    def __exit__(self, _, value, traceback):
        #self.close()
        return 

    def __enter__(self):
        #self.open()
        return self


# Define a main entry point for basic testing of the station without weewx
# engine and service overhead.  Invoke this as follows from the WeeWX root dir (i.e., /usr/bin/weewxd):
#
# sudo PYTHONPATH=/usr/share/weewx python /usr/share/weewx/user/BCRobotics.py
# 

if __name__ == '__main__':

    syslog.openlog('BCRobotics', syslog.LOG_PID | syslog.LOG_CONS)
    syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_DEBUG))
    
    with StationData() as s:
        #s.set_logger_mode()

        time.sleep(interval)
        while True:
            print (time.time(), s.get_readings())


Reply via email to