<<<Adding a Ecowitt Data Source to WeeWX

Add Ecowitt Data to WeeWX

The final step in the process is the add the new data source into the WeeWX database, but before we can do that we need to understand the contents of the files being uploaded

If we look at a data file we can see that the temperatures and humidity are contained in ab Array, I have obfuscated PASSKEY for obvioius reasons

Array
(
    [PASSKEY] => ################################
    [stationtype] => GW1000B_V1.6.3
    [dateutc] => 2021-01-16 12:30:13
    [tempinf] => 66.4
    [humidityin] => 42
    [baromrelin] => 28.981
    [baromabsin] => 28.981
    [tempf] => 40.3
    [humidity] => 79
    [wh26batt] => 0
    [freq] => 915M
    [model] => GW1000_Pro
)
    

Create Python Script to Parse the File

The data is well structured and so I have chosen to use a Python Dictionary to store the data, this was a simple task of identifying the Array key and assinging the associated value to a Python Dictionary element as shown.

I do plan to read the directory where the ecowitt data is stored from a variable in the config file, but for now I am using a constant

Another point to note in this program is that Ecowitt populates the directory with a file every minute whereas WeeWX reads the files every 5 minutes, so to handle that I order the files in the directory and delete all but the most recent file, which I then read and parse. This ensures that even if Ecowitt stops sending files for whatever reason there will always be at least 1 file in the directory and the process will succeed.

Again I may make this a bit more sophisticated going forward and do a timestamp check so that old data is not written into the database, but in the meantime the file is available for download here

Finally you will spot that I typecast the data I read into a float before inserting it into the database, this is because the data is stored as data type REAL in the database but when it is read from the text file it is assumed to be a string

pi@raspberrypi:~ $ vi ecowitt.py
import  os
import  weewx
from    weewx.engine  import  StdService
from    stat          import  S_ISREG, ST_MTIME, ST_MODE

ECOWITT_PATH  = '/var/www/html/ecowitt'

class AddEcowittData(StdService):

    def __init__(self, engine, config_dict):

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

      # Bind to any new archive record events:
      self.bind(weewx.NEW_ARCHIVE_RECORD, self.new_archive_record)

    def new_archive_record(self, event):

        lEcowittFiles =  (os.path.join(ECOWITT_PATH, sFiles)  for sFiles          in os.listdir(ECOWITT_PATH))
        lEcowittFiles = ((os.stat(sFullPath), sFullPath)      for sFullPath       in lEcowittFiles)
        lEcowittFiles = ((stat[ST_MTIME],     sFullPath)      for stat, sFullPath in lEcowittFiles if S_ISREG(stat[ST_MODE]))
        sDelFile      = ''

        for cDate, sFullPath in sorted(lEcowittFiles, reverse=False):
            if os.path.exists(sDelFile):
                os.remove(sDelFile)
                sDelFile = sFullPath
            else:
                sDelFile = sFullPath

        dEcowittData = {}
        ecowittData  = open(sFullPath, 'r')
        for sLineIn in ecowittData:
            if "[" in sLineIn:
                sKey    = sLineIn.split('[',  1)[1].split(']', 1)[0]
                sValue  = sLineIn.split('=>', 1)[1].strip()
                dEcowittData[sKey] = sValue

        ecowittData.close()

        event.record['extraTemp3']  = float(dEcowittData['tempinf'])
        event.record['extraHumid1'] = float(dEcowittData['humidityin'])
        event.record['extraTemp2']  = float(dEcowittData['tempf'])
        event.record['extraHumid2'] = float(dEcowittData['humidity'])
    

Put your Python Script into the Correct Directory

WeeWX scans a number of directories looking for scripts and files to run, one of those directories is a user directory where you can put all of your WeeWX extensions and this is where we are going to put this python file. Full documentation on customizing WeeWX can be found here

Copy your new Python script into the bin user directory under your WeeWX home directory

in my case this is /home/weewx

pi@weewx: $ cp ecowitt.py /home/weewx/bin/user/

pi@weewx: $ ls -al /home/weewx/bin/user/
total 48
drwxr-xr-x  3 pi root  4096 Jan 14 11:52 .
drwxr-xr-x 12 pi root  4096 Mar 28  2020 ..
-rw-r--r--  1 pi root   829 Mar 28  2020 cputemp.py
-rw-r--r--  1 pi root  4170 Jan 14 11:52 ecowitt.py
-rw-r--r--  1 pi root   541 Mar 14  2020 extensions.py
-rw-r--r--  1 pi root   306 Mar 14  2020 __init__.py
drwxr-xr-x  2 pi root  4096 Jan 14 11:52 __pycache__
-rwxr-xr-x  1 pi pi    7327 Mar 28  2020 s3backup.py
-rwxr-xr-x  1 pi pi   11041 Mar 28  2020 s3upload.py
-rwxr-xr-x  1 pi pi    3992 Mar 28  2020 stats.py
    

Now configure weewx.conf

Before your WeeWX installation will start processing the Ecowitt data, you have to tell WeeWX to run your new Python script.

This is done by modifying the Services section of your weewx configuration file and I know there are some fancy ways of doing this programatically, but I simply edit the file by adding a new entry for my new Python script

The syntax of this new entry is critical and is explained below

data_services = user.ecowitt.AddEcowittData

pi@weewx: $ vi weewx.conf

#   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.cputemp.AddCpuTemp, user.ecowitt.AddEcowittData
        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
    

Set Heading Text

This file also contains the labels that are used as the headings for each graph, and they are defined in the Labels section

Look for the value extraTemp1 and set the text to a value of your choice, I have used CPU Temperature

pi@weewx: $ vi weewx.conf

      # The labels to be used for each observation type
      [[[Labels]]]
      ...
      # Generic labels, keyed by an observation type.
      [[[[Generic]]]]
      barometer       = Barometer
      ...
      windvec         = Wind Vector
      extraTemp1      = CPU Temperature
      extraTemp2      = Caravan Temperature
      extraTemp3      = Lounge Temperature
      extraHumid2     = Caravan Humidity
      extraHumid1     = Lounge Humidity
    

Set Quality Control Checks

This file also contains a section for quality control where we can define the units and ranges for the database fields

As we are using some extra fields it is a good idea to set the values in this section

pi@weewx: $ vi weewx.conf

[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
        extraTemp1  =  10, 200,  degree_F
        extraTemp2  = -40, 120,  degree_F
        extraTemp3  =  10, 120,  degree_F
        extraHumid2 =   0, 100
        extraHumid1 =   0, 100
    

Add The New Temperature Graph

The creation of graphs is controlled in skin.conf and the one is use is the new Seasons file and this is the modification I will be descrbing

As with the other configuartion files I manually edit this configuration file, adding a new entry between %tempin and %rain to generate the new graphs as shown below

Note that we are creating four graphs here, daily, weekly, monthly and yearly

pi@weewx: $ vi skin.conf

        [[[dayCaravantemp]]]
            [[[[extraTemp2]]]]

        [[[dayLoungetemp]]]
            [[[[extraTemp3]]]]

        [[[weekCaravantemp]]]
            [[[[extraTemp2]]]]

        [[[weekLoungetemp]]]
            [[[[extraTemp3]]]]

        [[[monthCaravantemp]]]
            [[[[extraTemp2]]]]

        [[[monthLoungetemp]]]
            [[[[extraTemp3]]]]

        [[[yearCaravantemp]]]
            [[[[extraTemp2]]]]

        [[[yearLoungetemp]]]
            [[[[extraTemp3]]]]
    

Finally Display the new Graphs

Creating the graph is only half the battle, you also have to tell WeeWX to display the new graph, I have chosen to display my graph in the Maion section and that is the example that I will be using below

First you need to locate the template that is used to generate the WEB pages, for the Sensor Status this is index.html.tmpl

As with the previous changes, formatting is critical and in this file you are telling the WeeWX engine which files to display and the name you use in this file must match the name you generated in the skin.conf file, in my case this is daytemp, weektemp, monthtemp and yeartemp

pi@weewx: $ vi index.html.tmpl

        <div id="history_day" class="plot_container">
          <img src="daytempdew.png"       alt="$obs.label.outTemp" />
          <img src="dayCaravantemp.png"   alt="$obs.label.extraTemp2" />
          <img src="daytempin.png"        alt="$obs.label.inTemp" />
          <img src="dayLoungetemp.png"    alt="$obs.label.extraTemp3" />

        <div id="history_week" class="plot_container" style="display:none">
          <img src="weektempdew.png"      alt="$obs.label.outTemp" />
          <img src="weekCaravantemp.png"  alt="$obs.label.extraTemp2" />
          <img src="weektempin.png"       alt="$obs.label.inTemp" />
          <img src="weekLoungetemp.png"   alt="$obs.label.extraTemp3" />

        <div id="history_month" class="plot_container" style="display:none">
          <img src="monthtempdew.png"     alt="$obs.label.outTemp" />
          <img src="monthCaravantemp.png" alt="$obs.label.extraTemp2" />
          <img src="monthtempin.png"      alt="$obs.label.inTemp" />
          <img src="monthLoungetemp.png"  alt="$obs.label.extraTemp3" />

        <div id="history_year" class="plot_container" style="display:none">
          <img src="yeartempdew.png"      alt="$obs.label.outTemp" />
          <img src="yearCaravantemp.png"  alt="$obs.label.extraTemp2" />
          <img src="yeartempin.png"       alt="$obs.label.inTemp" />
          <img src="yearLoungetemp.png"   alt="$obs.label.extraTemp3" />
    

I also chose to display the data in the HiLo section, and this is done by making these changes to hilo.inc

pi@weewx: $ vi index.html.tmpl

<tr>
  <td class="label">$obs.label.extraTemp2</td>
  #for $archive in $archive_data
  <td class="data new_row hilo_$archive[0]">
    <span title="$archive[1].extraTemp2.maxtime">
      $archive[1].extraTemp2.max.format(add_label=False)</span><br/>
    <span title="$archive[1].extraTemp2.mintime">
      $archive[1].extraTemp2.min.format(add_label=False)</span>
  </td>
  #end for
  <td class="units">$unit.label.extraTemp2</td>
</tr>
    

And that is it, you should now get a your new graphs on your front page, someting like this