forked from weewx/weewx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
wee_config
executable file
·305 lines (250 loc) · 13.2 KB
/
wee_config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
#!/usr/bin/env python
#
# Copyright (c) 2009-2015 Tom Keffer <[email protected]>
#
# See the file LICENSE.txt for your full rights.
#
"""Configure the configuration file."""
from __future__ import with_statement
import sys
import syslog
import optparse
import configobj
import weewx
import weeutil.weeutil
import config_util
stn_info_defaults = {'location' : '',
'latitude' : '0',
'longitude' : '0',
'altitude' : ['0', 'meter'],
'units' : 'metric',
'station_type' : 'Vantage',
'driver' : 'weewx.drivers.Vantage'}
usage="""wee_config --help
wee_config --version
wee_config --list-drivers
wee_config --install --dist-config=DIST_CONFIG --output=OUT_CONFIG
[--driver=DRIVER]
[--latitude=yy.y] [--longitude=xx.x] [--altitude=zz.z,(foot|meter)]
[--location="Home Sweet Home"] [--units=(us|metric)]
[--no-prompt]
wee_config --update CONFIG_FILE|--config=CONFIG_FILE --dist-config=DIST_CONFIG
[--output=OUT_CONFIG] [--no-prompt]
wee_config --merge CONFIG_FILE|--config=CONFIG_FILE --dist-config=DIST_CONFIG
--output=OUT_CONFIG
wee_config --modify CONFIG_FILE|--config=CONFIG_FILE
[--driver=DRIVER]
[--latitude=yy.y] [--longitude=xx.x] [--altitude=zz.z,(foot|meter)]
[--location="Home Sweet Home"] [--units=(us|metric)]
[--output=OUT_CONFIG] [--no-prompt]
COMMANDS:
--help Print instructions, then exit.
--version Print the version of weewx, then exit.
--list-drivers List the available weewx device drivers, then exit.
--install Install DIST_CONFIG to OUT_CONFIG, prompting as necessary.
--update Update the contents of configuration file CONFIG_FILE,
then merge the result into configuration file DIST_CONFIG.
Write the results to CONFIG_FILE unless an OUT_CONFIG
is specified.
--merge Update the contents of configuration file CONFIG_FILE,
then merge the result into configuration file DIST_CONFIG.
Write the results to OUT_CONFIG.
--modify Modify the configuration file, prompting as necessary.
Use this to add a driver.
wee_config is used to configure your weewx configuration file (nominally,
weewx.conf). Its location can be given as a command-line argument,
or it can be specified with option --config.
"""
def main():
# Set defaults for the system logger:
syslog.openlog('wee_config', syslog.LOG_PID|syslog.LOG_CONS)
# Create a command line parser:
parser = optparse.OptionParser(usage=usage)
# Add the various options:
parser.add_option("--version", action="store_true",
help="Print the version of weewx and exit.")
parser.add_option("--list-drivers", action="store_true",
help="List all the available weewx device drivers, then exit.")
parser.add_option("--install", action="store_true",
help="Install DIST_CONFIG to OUT_FILE. Prompt as necessary.")
parser.add_option("--update", action="store_true",
help="Update an existing configuration file to the current version, then merge "
"into DIST_CONFIG. Save results to CONFIG_FILE.")
parser.add_option("--merge", action="store_true",
help="Update an existing configuration file to the current version, then merge "
"into DIST_CONFIG. Save results to OUT_CONFIG.")
parser.add_option("--modify", action="store_true",
help="Modify the configuration file. Prompt as necessary.")
parser.add_option("--config", dest="config_path", metavar="CONFIG_FILE",
help="Use configuration file CONFIG_FILE.")
parser.add_option("--dist-config",
help="Path to the new, incoming configuration file. This is usually supplied "
"by a distribution.")
parser.add_option("--output", metavar="OUT_CONFIG",
help="Where the results should be written.")
parser.add_option("--no-prompt", action="store_true",
help="Do not issue prompts. Use default values or specified options.")
parser.add_option("--driver", metavar="DRIVER", dest="driver",
help="Use the driver DRIVER, e.g., weewx.driver.vantage. ")
parser.add_option("--latitude", metavar="yy.y",
help="The station latitude")
parser.add_option("--longitude", metavar="xx.x",
help="The station longitude")
parser.add_option("--altitude", metavar="zz,(foot|meter)",
help="The station altitude in either feet or meters. E.g., '750,foot'")
parser.add_option("--location",
help="""A text description of the station. For example, "Santa's workshop, North Pole" """)
parser.add_option("--units", choices=["us", "metric"], metavar="(metric|us)",
help="Set display units to 'metric' or 'us'")
parser.add_option("--debug", action="store_true",
help="Print some intermediate data structures")
# Now we are ready to parse the command line:
(options, args) = parser.parse_args()
config_mgr = WeeConfig()
sys.exit(config_mgr.run(args, options))
class WeeConfig(object):
def run(self, args, options):
if options.version:
print weewx.__version__
sys.exit(0)
if options.list_drivers:
config_util.print_drivers()
sys.exit(0)
#
# Check for errors in the options.
#
# Can have only one of install, update, and merge:
if sum(1 if x is True else 0 for x in [options.install, options.update, options.merge]) > 1:
exit("Can have only one of install, update, or merge")
# Check for missing --dist-config
if (options.install or options.update or options.merge) and not options.dist_config:
exit("Command requires option --dist-config to be specified.")
# The install and merge options requires --output
if (options.install or options.merge) and not options.output:
sys.exit("Command requires option --output to be specified.")
# The install option does not take an old config file
if options.install and (options.config_path or len(args)):
sys.exit("Command --install does not allow an old config file.")
# Flag for whether the output needs to be saved:
save_me = False
if options.install or options.update or options.merge:
# Open up and parse the distribution config file:
try:
dist_config_dict = configobj.ConfigObj(options.dist_config, file_error=True)
except IOError, e:
sys.exit(str(e))
except SyntaxError, e:
sys.exit("Syntax error in distribution configuration file '%s': %s" %
(options.dist_config, e))
if options.install:
config_dict = dist_config_dict
config_path = options.output
else:
config_path, config_dict = config_util.read_config(options.config_path, args)
print "Using configuration file found at", config_path
# Update the old configuration file:
config_util.update_config(config_dict)
# Then merge it into the distribution file
config_util.merge_config(config_dict, dist_config_dict)
save_me = True
if options.install or options.modify:
self.modify_config(config_dict, options)
save_me = True
if save_me:
self.save_config(config_dict, config_path)
else:
print "Nothing done."
return 0
def modify_config(self, config_dict, options):
"""Modify the configuration dictionary according to any command
line options. Give the user a chance too.
"""
# Extract stn_info from the config_dict and command-line options:
stn_info = self.get_stn_info(config_dict, options)
# Get the driver editor, name, and version:
driver = stn_info.get('driver')
try:
# Look up driver info:
driver_editor, driver_name, driver_version = \
config_util.load_driver_editor(driver)
except Exception, e:
exit("Driver %s failed to load: %s" (driver, e))
stn_info['station_type'] = driver_name
print 'Using %s version %s (%s)' % (stn_info['station_type'], driver_version, driver)
if options.debug:
print "Station info:\n", weeutil.weeutil.print_dict(stn_info)
# Get a driver stanza, if possible
stanza = None
if driver_editor is not None:
orig_stanza_text = None
# if a previous stanza exists for this driver, grab it
if driver_name in config_dict:
orig_stanza = configobj.ConfigObj(interpolation=False)
orig_stanza[driver_name] = config_dict[driver_name]
orig_stanza_text = '\n'.join(orig_stanza.write())
# let the driver process the stanza or give us a new one
stanza_text = driver_editor.get_conf(orig_stanza_text)
stanza = configobj.ConfigObj(stanza_text.splitlines())
# If we have a stanza, inject it into the configuration dictionary
if stanza is not None:
# Insert the stanza in the configuration dictionary:
config_dict[driver_name] = stanza[driver_name]
# Add a major comment deliminator:
config_dict.comments[driver_name] = config_util.major_comment_block
# If we have a [Station] section, the move the new stanza to just after it
if 'Station' in config_dict:
config_util.reorder_sections(config_dict, driver_name, 'Station', after=True)
# make the stanza the station type
config_dict['Station']['station_type'] = driver_name
# Apply any overrides from the stn_info
if stn_info is not None:
# Update driver stanza with any overrides from stn_info
if driver_name in stn_info:
for k in stn_info[driver_name]:
config_dict[driver_name][k] = stn_info[driver_name][k]
# Update station information with stn_info overrides
for p in ['location', 'latitude', 'longitude', 'altitude']:
if stn_info.get(p) is not None:
config_dict['Station'][p] = stn_info[p]
# Update units display with any stn_info overrides
if stn_info.get('units') is not None:
if stn_info.get('units') in ['metric', 'metricwx']:
print "Using Metric units for display"
config_dict['StdReport']['StandardReport'].update({
'Units': {
'Groups': config_util.metricwx_group}})
elif stn_info.get('units') == 'us':
print "Using US units for display"
config_dict['StdReport']['StandardReport'].update({
'Units': {
'Groups': config_util.us_group}})
def get_stn_info(self, config_dict, options):
"""Build the stn_info structure. This generally contains stuff
that wee_config can inject into the config_dict."""
# Get defaults out of the config file:
stn_info = config_util.get_station_info(config_dict)
# Get command line overrides, and apply them to stn_info:
for k in stn_info:
# Override only if the option exists and is not None:
if hasattr(options, k) and getattr(options,k) is not None:
stn_info[k] = getattr(options, k)
# If any are still None, replace them with defaults:
for k in stn_info_defaults:
if k not in stn_info or stn_info[k] is None:
stn_info[k] = stn_info_defaults[k]
# Unless --no-prompt has been specified, give the user a chance to change things:
if not options.no_prompt:
stn_info.update(config_util.prompt_for_info(**stn_info))
if not options.driver:
driver = config_util.prompt_for_driver(stn_info.get('driver'))
stn_info['driver'] = driver
stn_info.update(config_util.prompt_for_driver_settings(driver))
return stn_info
def save_config(self, config_dict, config_path):
"""Save the config file, backing up as necessary."""
backup_path = config_util.save_config(config_dict, config_path)
if backup_path:
print "Saved backup to %s" % backup_path
print "Saved configuration file to %s" % config_path
if __name__=="__main__" :
main()