X-Git-Url: https://wylark.com/src/infoex-autowx.git/blobdiff_plain/6ec26a0bca8fc3aee9fdd72dfeb920adf7dc8ff8..e7abb7e4b661ecbf466c1934ce3e34e1a9ea1a68:/infoex-autowx.py diff --git a/infoex-autowx.py b/infoex-autowx.py index 5f35d0e..e4befad 100755 --- a/infoex-autowx.py +++ b/infoex-autowx.py @@ -2,14 +2,15 @@ # -*- coding: utf-8 -*- """ -InfoEx <-> NRCS Auto Wx implementation +InfoEx <-> NRCS/MesoWest Auto Wx implementation Alexander Vasarab Wylark Mountaineering LLC -Version 1.0.0 +Version 2.0.0 -This program fetches data from an NRCS SNOTEL site and pushes it to -InfoEx using the new automated weather system implementation. +This program fetches data from either an NRCS SNOTEL site or MesoWest +weather station and pushes it to InfoEx using the new automated weather +system implementation. It is designed to be run hourly, and it asks for the last three hours of data of each desired type, and selects the most recent one. This @@ -41,8 +42,10 @@ import zeep import zeep.cache import zeep.transports +__version__ = '2.0.0' + log = logging.getLogger(__name__) -log.setLevel(logging.DEBUG) +log.setLevel(logging.NOTSET) try: from systemd.journal import JournalHandler @@ -55,11 +58,18 @@ except: handler = logging.StreamHandler(sys.stdout) log.addHandler(handler) -parser = OptionParser() +parser = OptionParser(version=__version__) + parser.add_option("--config", dest="config", metavar="FILE", help="location of config file") + +parser.add_option("--log-level", + dest="log_level", + default=None, + help="set the log level (debug, info, warning)") + parser.add_option("--dry-run", action="store_true", dest="dry_run", @@ -71,14 +81,25 @@ parser.add_option("--dry-run", config = configparser.ConfigParser(allow_no_value=False) if not options.config: - print("Please specify a configuration file via --config") + parser.print_help() + print("\nPlease specify a configuration file via --config.") sys.exit(1) config.read(options.config) -if 'nrcs' in config and 'mesowest' in config: - print("Both MesoWest and NRCS configuration option specified, " - "please choose just one.") +# ugly, but passable +if options.log_level in [None, 'debug', 'info', 'warning']: + if options.log_level == 'debug': + log.setLevel(logging.DEBUG) + elif options.log_level == 'info': + log.setLevel(logging.INFO) + elif options.log_level == 'warning': + log.setLevel(logging.WARNING) + else: + log.setLevel(logging.NOTSET) +else: + parser.print_help() + print("\nPlease select an appropriate log level or remove the switch (--log-level).") sys.exit(1) log.debug('STARTING UP') @@ -94,14 +115,18 @@ try: } data = dict() + data['provider'] = config['station']['type'] + + if data['provider'] not in ['nrcs', 'mesowest']: + print("Please specify either nrcs or mesowest as the station type.") + sys.exit(1) - if 'nrcs' in config: - data['provider'] = 'nrcs' + if data['provider'] == 'nrcs': data['source'] = 'https://www.wcc.nrcs.usda.gov/awdbWebService/services?WSDL' - data['stationID'] = config['nrcs']['station_triplet'] + data['station_id'] = config['station']['station_id'] try: - desired_data = config['nrcs']['desired_data'].split(',') + desired_data = config['station']['desired_data'].split(',') except: # desired_data malformed or missing, setting default desired_data = [ @@ -110,21 +135,24 @@ try: 'PREC' # PRECIPITATION ACCUMULATION (in) ] - if 'mesowest' in config: - data['provider'] = 'mesowest' - #data['source'] = 'https://api.synopticdata.com/v2/stations/latest' + # XXX: For NRCS, we're manually overriding units for now! Once + # unit conversion is supported for NRCS, REMOVE THIS! + if 'units' not in data: + data['units'] = 'imperial' + + if data['provider'] == 'mesowest': data['source'] = 'https://api.synopticdata.com/v2/stations/timeseries' - data['stationID'] = config['mesowest']['stid'] - data['units'] = config['mesowest']['units'] + data['station_id'] = config['station']['station_id'] + data['units'] = config['station']['units'] try: - desired_data = config['mesowest']['desired_data'] + desired_data = config['station']['desired_data'] except: # desired_data malformed or missing, setting default desired_data = 'air_temp,snow_depth' - # construct full API URL - data['source'] = data['source'] + '?token=' + config['mesowest']['token'] + '&within=60&units=' + data['units'] + '&stid=' + data['stationID'] + '&vars=' + desired_data + # construct full API URL (sans start/end time, added later) + data['source'] = data['source'] + '?token=' + config['station']['token'] + '&within=60&units=' + data['units'] + '&stid=' + data['station_id'] + '&vars=' + desired_data except KeyError as e: log.critical("%s not defined in %s" % (e, options.config)) @@ -184,7 +212,7 @@ fmap['hn24AutoUnit'] = 26 ; final_data[26] = 'in' fmap['hstAuto'] = 27 ; final_data[27] = None fmap['hstAutoUnit'] = 28 ; final_data[28] = 'in' -# one final mapping, the NRCS fields that this program supports to +# one final mapping, the NRCS/MesoWest fields that this program supports to # their InfoEx counterpart iemap = {} @@ -192,10 +220,35 @@ if data['provider'] == 'nrcs': iemap['PREC'] = 'precipitationGauge' iemap['TOBS'] = 'tempPres' iemap['SNWD'] = 'hS' + iemap['PRES'] = 'baro' + iemap['RHUM'] = 'rH' + iemap['WSPD'] = 'windSpeedNum' + iemap['WDIR'] = 'windDirectionNum' + # unsupported by NRCS: + # windGustSpeedNum elif data['provider'] == 'mesowest': iemap['precip_accum'] = 'precipitationGauge' iemap['air_temp'] = 'tempPres' iemap['snow_depth'] = 'hS' + iemap['pressure'] = 'baro' + iemap['relative_humidity'] = 'rH' + iemap['wind_speed'] = 'windSpeedNum' + iemap['wind_direction'] = 'windDirectionNum' + iemap['wind_gust'] = 'windGustSpeedNum' + +# override units if user selected metric +# +# NOTE: to update this, use the fmap<->final_data mapping laid out above +# +# NOTE: this only 'works' with MesoWest for now, as the MesoWest API +# itself handles the unit conversion; in the future, we will also +# support NRCS unit conversion, but this must be done by this +# program. +if data['units'] == 'metric': + final_data[fmap['tempPresUnit']] = 'C' + final_data[fmap['hsUnit']] = 'm' + final_data[fmap['windSpeedUnit']] = 'm/s' + final_data[fmap['windGustSpeedNumUnit']] = 'm/s' # floor time to nearest hour dt = datetime.datetime.now() @@ -220,7 +273,7 @@ if data['provider'] == 'nrcs': # get the last three hours of data for this elementCd tmp = client.service.getHourlyData( - stationTriplets=[data['stationID']], + stationTriplets=[data['station_id']], elementCd=elementCd, ordinal=1, beginDate=begin_date,