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