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 [email protected].
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 ----