I'm cobbling together a driver that will ultimately seed its packets with a 
JSON query from the Davis WeatherLink Live hardware (mentioned in a 
separate thread).

I used mwall's suggestion to start with his maxbotix driver, and stripped a 
bunch of stuff out of it to basically have it generate a bogus _pkt set of 
parameters.

When I run this with --test-driver it does the expected thing, showing me 
the bogus packet's contents.  Cool.

root@stretch64pkg:/home/weewx/bin/user# PYTHONPATH=/home/weewx/bin python3 
/home/weewx/bin/user/vincetest.py --test-driver
testing driver
('2020-02-29 21:58:39 GMT (1583013519)', {'usUnits': 1, 'outTemp': 31.23, 
'dateTime': 1583013519})
('2020-02-29 21:58:42 GMT (1583013522)', {'usUnits': 1, 'outTemp': 31.23, 
'dateTime': 1583013522})
('2020-02-29 21:58:44 GMT (1583013524)', {'usUnits': 1, 'outTemp': 31.23, 
'dateTime': 1583013524})

 

But...when I run the driver in the foreground, check out the output...

root@stretch64pkg:/home/weewx/bin/user# /home/weewx/bin/weewxd 
/home/weewx/weewx.conf
LOOP:   2020-02-29 21:59:00 GMT (1583013540) dateTime: 1583013540, 
maxSolarRad: 525.2302552658722, outTemp: 31.23, rainRate: 0.0, usUnits: 1
LOOP:   2020-02-29 21:59:02 GMT (1583013542) dateTime: 1583013542, 
maxSolarRad: 525.1744219921469, outTemp: 31.23, rainRate: 0.0, usUnits: 1
LOOP:   2020-02-29 21:59:04 GMT (1583013544) dateTime: 1583013544, 
maxSolarRad: 525.1185872811789, outTemp: 31.23, rainRate: 0.0, usUnits: 1

 
Questions I have is : 

   - where did the  maxSolarRad and rainRate elements and values come from 
   ?  They're not mentioned in the driver at all.
   - does weewx have some stuff under the hood that is seeding elements 
   that don't necessarily exist in the gear a particular driver contains ?


Draft driver is attached in case anybody has ideas....


-- 
You received this message because you are subscribed to the Google Groups 
"weewx-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to weewx-development+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/weewx-development/20a03060-3493-4e3f-8573-c8ba8a2d942e%40googlegroups.com.
#!/usr/bin/python

'''

This is a test-use-only driver derived from mwall's maxbotix example (thanks Matthew!)
Any hacks/errors/omissions/crimes-against-python are all mine.

1.  install this driver in bin/user
2.  define this as the station_type

    [Station]
        station_type = vincetest

3. add a stanza for this station type

   [vincetest]
      driver = user.vincetest
      max_tries = 10
      retry_wait = 5
      polling_interval = 2
      url = http://192.168.1.18:80/conditions.json

4. to test the driver standalone

    PYTHONPATH=/home/weewx/bin python3 /home/weewx/bin/user/vincetest.py --test-driver

5. run the driver in the foreground

    /home/weewx/bin/weewxd /home/weewx/weewx.conf

6. run weewx in the background

    # probably move your old archive/weewx.sdb aside to start anew
    
    # start weewx and verify it's running
    systemctl start weewx
    systemctl status weewx

    # wait 5 minutes, watching your syslog to see it save an archive record then:
      echo 'select * from archive; | sqlite3 /home/weewx/archive/weewx.sdb
    
'''

import serial   # vds: not needed in the real json/http based driver, to be deleted
import syslog
import time

import weewx.drivers
import weewx.engine
import weewx.units

DRIVER_NAME = "vincetest"
DRIVER_VERSION = "0.0.1"

def logmsg(dst, msg):
    syslog.syslog(dst, 'vincetest: %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 loader(config_dict, engine):
    return vincetestDriver(**config_dict['vincetest'])

schema = [('dateTime',  'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
          ('usUnits',   'INTEGER NOT NULL'),
          ('interval',  'INTEGER NOT NULL'),
          ('range',     'REAL')]

weewx.units.obs_group_dict['range'] = 'group_range'
weewx.units.obs_group_dict['range2'] = 'group_range'
weewx.units.obs_group_dict['range3'] = 'group_range'
weewx.units.USUnits['group_range'] = 'inch'
weewx.units.MetricUnits['group_range'] = 'cm'
weewx.units.MetricWXUnits['group_range'] = 'cm'


class vincetestDriver(weewx.drivers.AbstractDevice):

    def __init__(self, **stn_dict):
        loginf("driver version is %s" % DRIVER_VERSION)
        self.max_tries = int(stn_dict.get('max_tries', 5))
        self.retry_wait = int(stn_dict.get('retry_wait', 10))
        self.poll_interval = float(stn_dict.get('poll_interval', 2))
        loginf("polling interval is %s" % self.poll_interval)

    @property
    def hardware_name(self):
        return "vincetest"

    def genLoopPackets(self):
        ntries = 0
        while ntries < self.max_tries:
            ntries += 1
            try:
                #vds: commented out mwalls' example - we'd do our json query and packet construction here
                #with Sensor(self.model, self.port) as sensor:
                    #v = sensor.get_range()
                ntries = 0
                # vds - this is a clearly bogus packet for test purposes
                _packet = {'dateTime': int(time.time() + 0.5),
                           'usUnits': weewx.US,
                           'outTemp': 31.23 }
                yield _packet
                if self.poll_interval:
                    time.sleep(self.poll_interval)
            # vds: this won't check for serial connection in a real json http query driver of course
            except (serial.serialutil.SerialException, weewx.WeeWxIOError) as e:
                logerr("Failed attempt %d of %d to get LOOP data: %s" %
                       (ntries, self.max_tries, e))
                time.sleep(self.retry_wait)
        else:
            msg = "Max retries (%d) exceeded for LOOP data" % self.max_tries
            logerr(msg)
            raise weewx.RetriesExceeded(msg)


class Sensor():

    # information about each type of sensor.  the key is the model number.  the
    # associated tuple contains the units of the value that is returned, the
    # value the sensor returns when the range is maxxed out, and the number or
    # characters (excluding the R and trailing newline) in the value string.
    MODEL_INFO = {
        'MB1040': ['inch', 254, 3], # 6in min; 254in max; 1in res
        }

    def __init__(self, model, port, baudrate=9600, timeout=1):
        self.model = model
        self.port = port
        self.baudrate = baudrate
        self.timeout = timeout
        self.serial_port = None
        model_info = Sensor.MODEL_INFO[self.model]
        self.units = model_info[0]
        self.no_target = model_info[1]
        self.data_length = model_info[2]

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

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

    def open(self):
        self.serial_port = serial.Serial(self.port, self.baudrate,
                                         timeout=self.timeout)

    def close(self):
        if self.serial_port is not None:
            self.serial_port.close()
            self.serial_port = None

# this is where we'd get the json and deconstruct it
    def get_range(self):
        # return value is always mm
        line = self.serial_port.read(self.data_length + 2)
        if line:
            line = line.strip()
        if line and len(line) == self.data_length + 1 and line[0] == 'R':
            try:
                v = int(line[1:])
                if v == self.no_target:
                    logdbg("no target detected: v=%s" % v)
                    v = None
                if self.units == 'inch':
                    v *= 25.4
                return v
            except ValueError as e:
                raise weewx.WeeWxIOError("bogus value: %s" % e)
        else:
            raise weewx.WeeWxIOError("unexpected line: '%s'" % line)


# To test this driver, do the following:
#   PYTHONPATH=/home/weewx/bin python /home/weewx/bin/user/vincetest.py
if __name__ == "__main__":
    usage = """%prog [options] [--help]"""

    def main():
        import optparse
        syslog.openlog('wee_vincetest', syslog.LOG_PID | syslog.LOG_CONS)
        parser = optparse.OptionParser(usage=usage)
        parser.add_option('--url', dest="url", metavar="URL ",
                default='http://192.168.1.18:80/conditions.json',
                help="The URL to query.  Default is 'http://192.168.1.18:80/conditions.json'")
        parser.add_option('--test-driver', dest='td', action='store_true',
                          help='test the driver')
        (options, args) = parser.parse_args()

        if  options.td:
            test_driver()

    def test_driver():
        import weeutil.weeutil
        driver = vincetestDriver()
        print("testing driver")
        for pkt in driver.genLoopPackets():
            print((weeutil.weeutil.timestamp_to_string(pkt['dateTime']), pkt))

    main()

#---- that's all folks ----

Reply via email to