def get_series(obs_type, timespan, db_manager, aggregate_type=None, aggregate_interval=None): """Get a series, possibly with aggregation, from the main archive database. The general strategy is that if aggregation is asked for, chop the series up into separate chunks, calculating the aggregate for each chunk. Then assemble the results. If no aggregation is called for, just return the data directly out of the database. """ startstamp, stopstamp = timespan start_vec = list() stop_vec = list() data_vec = list() if aggregate_type: # With aggregation unit, unit_group = None, None if aggregate_type == 'cumulative': total = 0 for stamp in weeutil.weeutil.intervalgen(startstamp, stopstamp, aggregate_interval): agg_vt = get_aggregate(obs_type, stamp, aggregate_type, db_manager) if unit: # It's OK if the unit is unknown (=None). if agg_vt[1] is not None and (unit != agg_vt[1] or unit_group != agg_vt[2]): raise weewx.UnsupportedFeature("Cannot change unit groups within an aggregation.") else: unit, unit_group = agg_vt[1:] start_vec.append(stamp.start) stop_vec.append(stamp.stop) if aggregate_type == 'cumulative': total += agg_vt[0] data_vec.append(total) else: data_vec.append(agg_vt[0]) else: # Without aggregation. We only know how to get series that are in the database schema: if obs_type not in db_manager.sqlkeys: raise weewx.UnknownType(obs_type) # No aggregation sql_str = "SELECT dateTime, %s, usUnits, `interval` FROM %s " \ "WHERE dateTime >= ? AND dateTime <= ?" % (obs_type, db_manager.table_name) std_unit_system = None for record in db_manager.genSql(sql_str, (startstamp, stopstamp)): if std_unit_system: if std_unit_system != record[2]: raise weewx.UnsupportedFeature("Unit type cannot change within an aggregation interval.") else: std_unit_system = record[2] start_vec.append(record[0] - record[3] * 60) stop_vec.append(record[0]) data_vec.append(record[1]) unit, unit_group = weewx.units.getStandardUnitType(std_unit_system, obs_type, aggregate_type) return (ValueTuple(start_vec, 'unix_epoch', 'group_time'), ValueTuple(stop_vec, 'unix_epoch', 'group_time'), ValueTuple(data_vec, unit, unit_group))
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % ( 'RsyncThread ' + RSYNC_THREAD_VERSION, REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(ThreadedRsyncInstaller, self).__init__( version=RSYNC_THREAD_VERSION, name='RsyncThread', description= 'weeWX support for anytime transfer of files using rsync.', author="Gary Roderick", author_email="*****@*****.**", archive_services=['user.rsyncthread.Rsync'], config={ 'RsyncThread': { 'enable': 'True', 'remote_path': 'replace_me', 'server': 'replace_me', 'user': '******', 'port': '', 'delete': '', 'ssh_timeout': '2', 'rsync_timeout': '2' } }, files=[('bin/user', ['bin/user/rsyncthread.py'])])
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires WeeWX %s or greater, found %s" % (''.join( ('GW1000 driver ', GW1000_VERSION)), REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(Gw1000Installer, self).__init__( version=GW1000_VERSION, name='GW1000', description='WeeWX driver for GW1000 WiFi gateway.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", files=[('bin/user', ['bin/user/gw1000.py'])], config={ 'GW1000': { 'driver': 'user.gw1000' }, 'Accumulator': { 'lightning_strike_count': { 'extractor': 'sum' }, 'lightning_last_det_time': { 'extractor': 'last' } } })
def get_series(obs_type, timespan, db_manager, aggregate_type=None, aggregate_interval=None, **option_dict): """Get a series, possibly with aggregation, for special 'wind vector' types. These are typically used for the wind vector plots. """ # Check to see if the requested type is not 'windvec' or 'windgustvec' if obs_type not in WindVec.windvec_types: # The type is not one of the extended wind types. We can't handle it. raise weewx.UnknownType(obs_type) # It is an extended wind type. Prepare the lists that will hold the # final results. start_vec = list() stop_vec = list() data_vec = list() # Is aggregation requested? if aggregate_type: # Yes. Just use the regular series function. When it comes time to do the aggregation, # the specialized function WindVec.get_aggregate() (defined below), will be used. return ArchiveTable.get_series(obs_type, timespan, db_manager, aggregate_type, aggregate_interval) else: # No aggregation desired. However, we have will have to assemble the wind vector from # its flattened types. This SQL select string will select the proper wind types sql_str = 'SELECT dateTime, %s, %s, usUnits, `interval` FROM %s ' \ 'WHERE dateTime >= ? AND dateTime <= ?' \ % (WindVec.windvec_types[obs_type][0], WindVec.windvec_types[obs_type][1], db_manager.table_name) std_unit_system = None for record in db_manager.genSql(sql_str, timespan): ts, magnitude, direction, unit_system, interval = record if std_unit_system: if std_unit_system != unit_system: raise weewx.UnsupportedFeature( "Unit type cannot change within a time interval.") else: std_unit_system = unit_system value = weeutil.weeutil.to_complex(magnitude, direction) start_vec.append(ts - interval * 60) stop_vec.append(ts) data_vec.append(value) unit, unit_group = weewx.units.getStandardUnitType( std_unit_system, obs_type, aggregate_type) return (ValueTuple(start_vec, 'unix_epoch', 'group_time'), ValueTuple(stop_vec, 'unix_epoch', 'group_time'), ValueTuple(data_vec, unit, unit_group))
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % ('Rtd ' + RTGD_VERSION, REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(RtdInstaller, self).__init__( version=RTD_VERSION, name='Rtd', description='Create a user defined JSON data string that can then be saved to file, dispatched to a URL via HTTP POST or dispatched as a message to a MQTT broker.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", report_services=['user.rtd.RealtimeJSON'], config={ 'RealtimeJSON': { 'windrun_loop': 'false', 'max_cache_age': '600', 'Calculate': { 'atc': '0.8', 'nfac': '2', 'Algorithm': { 'maxSolarrad': 'RS' } } 'DecimalPlaces': { 'degree_C': '2', 'degree_F': '2', 'degree_compass': '******', 'foot': '2', 'hPa': '2', 'inHg': '4', 'inch': '3', 'inch_per_hour': '3', 'km_per_hour': '1', 'km': '2', 'mbar': '2', 'meter': '1', 'meter_per_second': '2', 'mile': '2', 'mile_per_hour': '1', 'mm': '2', 'mm_per_hour': '2', 'percent': '1', 'uv_index': '2', 'watt_per_meter_squared': '1' }, 'Groups': { 'group_altitude': 'foot', 'group_pressure': 'hPa', 'group_rain': 'mm', 'group_speed': 'km_per_hour', 'group_temperature': 'degree_C' }, } }, files=[('bin/user', ['bin/user/rtd.py'])] )
def get_series(obs_type, timespan, db_manager, aggregate_type=None, aggregate_interval=None): """Get a series, possibly with aggregation. """ if obs_type not in [ 'pm2_5_aqi', 'pm2_5_aqi_color' ]: raise weewx.UnknownType(obs_type) log.debug('get_series(%s, %s, %s, aggregate:%s, aggregate_interval:%s)' % ( obs_type, timestamp_to_string(timespan.start), timestamp_to_string( timespan.stop), aggregate_type, aggregate_interval)) # Prepare the lists that will hold the final results. start_vec = list() stop_vec = list() data_vec = list() # Is aggregation requested? if aggregate_type: # Yes. Just use the regular series function. return weewx.xtypes.ArchiveTable.get_series(obs_type, timespan, db_manager, aggregate_type, aggregate_interval) else: # No aggregation. sql_str = 'SELECT dateTime, usUnits, `interval`, pm2_5 FROM %s ' \ 'WHERE dateTime >= ? AND dateTime <= ? AND pm2_5 IS NOT NULL' \ % db_manager.table_name std_unit_system = None for record in db_manager.genSql(sql_str, timespan): ts, unit_system, interval, pm2_5 = record if std_unit_system: if std_unit_system != unit_system: raise weewx.UnsupportedFeature( "Unit type cannot change within a time interval.") else: std_unit_system = unit_system if obs_type == 'pm2_5_aqi': value = AQI.compute_pm2_5_aqi(pm2_5) if obs_type == 'pm2_5_aqi_color': value = AQI.compute_pm2_5_aqi_color(AQI.compute_pm2_5_aqi(pm2_5)) log.debug('get_series(%s): %s - %s - %s' % (obs_type, timestamp_to_string(ts - interval * 60), timestamp_to_string(ts), value)) start_vec.append(ts - interval * 60) stop_vec.append(ts) data_vec.append(value) unit, unit_group = weewx.units.getStandardUnitType(std_unit_system, obs_type, aggregate_type) return (ValueTuple(start_vec, 'unix_epoch', 'group_time'), ValueTuple(stop_vec, 'unix_epoch', 'group_time'), ValueTuple(data_vec, unit, unit_group))
def get_series(obs_type, timespan, db_manager, aggregate_type=None, aggregate_interval=None): """Get a series, possibly with aggregation, for special 'wind' types.""" # Check to see if the requested type is not 'windvec' or 'windgustvec' if obs_type not in Wind.windvec_types: # The type is not one of the extended wind types. We can't handle it. raise weewx.UnknownType(obs_type) # It is an extended wind type. Prepare the lists that will hold the # final results. start_vec = list() stop_vec = list() data_vec = list() # Is aggregation requested? if aggregate_type: # Yes. Just use the regular series function, but with the special wind aggregate type. It will # call the proper aggregation function. return SeriesArchive.get_series(obs_type, timespan, db_manager, aggregate_type, aggregate_interval) else: # No aggregation desired. However, we have will have to assemble the wind vector from its flattened types. # This SQL select string will select the proper wind types sql_str = 'SELECT dateTime, %s, %s, usUnits, `interval` FROM %s WHERE dateTime >= ? AND dateTime <= ?' \ % (Wind.windvec_types[obs_type][0], Wind.windvec_types[obs_type][1], db_manager.table_name) std_unit_system = None for record in db_manager.genSql(sql_str, timespan): start_vec.append(record[0] - record[4] * 60) stop_vec.append(record[0]) if std_unit_system: if std_unit_system != record[3]: raise weewx.UnsupportedFeature("Unit type cannot change within a time interval.") else: std_unit_system = record[3] # Break the mag and dir down into x- and y-components. (magnitude, direction) = record[1:3] if magnitude is None or direction is None: data_vec.append(None) else: x = magnitude * math.cos(math.radians(90.0 - direction)) y = magnitude * math.sin(math.radians(90.0 - direction)) if weewx.debug: # There seem to be some little rounding errors that # are driving my debugging crazy. Zero them out if abs(x) < 1.0e-6: x = 0.0 if abs(y) < 1.0e-6: y = 0.0 data_vec.append(complex(x, y)) unit, unit_group = weewx.units.getStandardUnitType(std_unit_system, obs_type, aggregate_type) return (ValueTuple(start_vec, 'unix_epoch', 'group_time'), ValueTuple(stop_vec, 'unix_epoch', 'group_time'), ValueTuple(data_vec, unit, unit_group))
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % ( 'Rtgd ' + RTGD_VERSION, REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(RtgdInstaller, self).__init__( version=RTGD_VERSION, name='Rtgd', description= 'WeeWX support for near realtime updating of the SteelSeries Weather Gauges.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", report_services=['user.rtgd.RealtimeGaugeData'], config={ 'RealtimeGaugeData': { 'date_format': '%Y.%m.%d %H:%M', 'rtgd_path': '/home/weewx/public_html', 'scroller_source': 'text|file|WU|DS|Zambretti', 'StringFormats': { 'degree_C': '%.1f', 'degree_F': '%.1f', 'degree_compass': '******', 'foot': '%.0f', 'hPa': '%.1f', 'inHg': '%.2f', 'inch': '%.2f', 'inch_per_hour': '%.2f', 'km_per_hour': '%.1f', 'km': '%.1f', 'mbar': '%.1f', 'meter': '%.0f', 'meter_per_second': '%.1f', 'mile': '%.1f', 'mile_per_hour': '%.1f', 'mm': '%.1f', 'mm_per_hour': '%.1f', 'percent': '%.0f', 'uv_index': '%.1f', 'watt_per_meter_squared': '%.0f' }, 'Groups': { 'group_altitude': 'foot', 'group_pressure': 'hPa', 'group_rain': 'mm', 'group_speed': 'km_per_hour', 'group_temperature': 'degree_C' }, 'DS': { 'api_key': 'xxxxxxxxxxxxxxxx' } } }, files=[('bin/user', ['bin/user/rtgd.py'])])
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires WeeWX %s or greater, found %s" % (''.join( ('GW1000 driver ', GW1000_VERSION)), REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(Gw1000Installer, self).__init__( version=GW1000_VERSION, name='GW1000', description='WeeWX driver for GW1000 WiFi gateway.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", files=[('bin/user', ['bin/user/gw1000.py'])], config=gw1000_dict)
def get_series(obs_type, timespan, db_manager, aggregate_type=None, aggregate_interval=None, **option_dict): """Get a series of an xtype, by using the main archive table. Works only for no aggregation. """ start_vec = list() stop_vec = list() data_vec = list() if aggregate_type: # This version does not know how to do aggregations, although this could be # added in the future. raise weewx.UnknownAggregation(aggregate_type) else: # No aggregation std_unit_system = None # Hit the database. for record in db_manager.genBatchRecords(*timespan): if std_unit_system: if std_unit_system != record['usUnits']: raise weewx.UnsupportedFeature( "Unit system cannot change " "within a series.") else: std_unit_system = record['usUnits'] # Given a record, use the xtypes system to calculate a value: try: value = get_scalar(obs_type, record, db_manager) data_vec.append(value[0]) except weewx.CannotCalculate: data_vec.append(None) start_vec.append(record['dateTime'] - record['interval'] * 60) stop_vec.append(record['dateTime']) unit, unit_group = weewx.units.getStandardUnitType( std_unit_system, obs_type) return (ValueTuple(start_vec, 'unix_epoch', 'group_time'), ValueTuple(stop_vec, 'unix_epoch', 'group_time'), ValueTuple(data_vec, unit, unit_group))
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % (''.join( ('Bloomsky driver ', BLOOMSKY_VERSION)), REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(BloomskyInstaller, self).__init__( version=BLOOMSKY_VERSION, name='Bloomsky', description= 'WeeWX driver for Bloomsky Sky1/Sky2/Storm personal weather stations.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", files=[('bin/user', ['bin/user/bloomsky.py'])], config={ 'Bloomsky': { 'api_key': 'INSERT_API_KEY_HERE', 'poll_interval': 60, 'driver': 'user.bloomsky' }, 'Accumulator': { 'deviceID': { 'adder': 'noop' }, 'deviceName': { 'adder': 'noop' }, 'imageURL': { 'adder': 'noop' }, 'deviceType': { 'adder': 'noop' }, 'night': { 'adder': 'noop' }, 'imageTimestamp': { 'adder': 'noop' }, 'raining': { 'adder': 'noop' } } })
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_WEEWX_VERSION): msg = "%s requires WeeWX %s or greater, found %s" % (''.join(('WeeWX APRX ', APRX_VERSION)), REQUIRED_WEEWX_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(AprxInstaller, self).__init__( version=APRX_VERSION, name='APRX', description='WeeWX service to generate an APRX ready beacon file.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", files=[('bin/user', ['bin/user/aprx.py'])], process_services='user.aprx.WeewxAprx', config={ 'WeewxAprx': { }, } )
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % ( 'Rtcr ' + RTCR_VERSION, REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(RtcrInstaller, self).__init__( version=RTCR_VERSION, name='Rtcr', description= 'WeeWX support for near realtime generation of a limited clientraw.txt.', author="Gary Roderick", author_email="*****@*****.**", report_services=['user.rtcr.RealtimeClientraw'], config={ 'RealtimeClientraw': { 'rtcr_path': '/home/weewx/public_html' } }, files=[('bin/user', ['bin/user/rtcr.py'])])
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % ('PVOutput ' + PVOUTPUT_VERSION, REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(PVOutputInstaller, self).__init__( version=PVOUTPUT_VERSION, name='PVOutput', description='WeeWX RESTful service for uploading data to PVOutput.org.', author="Gary Roderick", author_email="*****@*****.**", restful_services=['user.pvoutput.StdPVOutput'], config={ 'StdRESTful': { 'PVOutput': { 'enable': 'false', 'system_id': 'ENTER_PVOUTPUT_SYSTEM_ID_HERE', 'api_key': 'ENTER_PVOUTPUT_API_KEY_HERE' } } }, files=[('bin/user', ['bin/user/pvoutput.py'])] )
def get_aggregate(obs_type, timespan, aggregate_type, db_manager, **option_dict): """Returns an aggregation of a wind vector type over a timespan by using the main archive table. obs_type: The type over which aggregation is to be done. For this function, it must be 'windvec' or 'windgustvec'. Anything else will cause weewx.UnknownType to be raised. timespan: An instance of weeutil.Timespan with the time period over which aggregation is to be done. aggregate_type: The type of aggregation to be done. For this function, must be 'avg', 'sum', 'count', 'first', 'last', 'min', or 'max'. Anything else will cause weewx.UnknownAggregation to be raised. db_manager: An instance of weewx.manager.Manager or subclass. option_dict: Not used in this version. returns: A ValueTuple containing the result. Note that the value contained in the ValueTuple will be a complex number. """ if obs_type not in WindVec.windvec_types: raise weewx.UnknownType(obs_type) aggregate_type = aggregate_type.lower() # Raise exception if we don't know about this type of aggregation if aggregate_type not in ['avg', 'sum'] + list(WindVec.agg_sql_dict.keys()): raise weewx.UnknownAggregation(aggregate_type) # Form the interpolation dictionary interpolation_dict = { 'dir': WindVec.windvec_types[obs_type][1], 'mag': WindVec.windvec_types[obs_type][0], 'start': weeutil.weeutil.startOfDay(timespan.start), 'stop': timespan.stop, 'table_name': db_manager.table_name } if aggregate_type in WindVec.agg_sql_dict: # For these types (e.g., first, last, etc.), we can do the aggregation in a SELECT statement. select_stmt = WindVec.agg_sql_dict[aggregate_type] % interpolation_dict row = db_manager.getSql(select_stmt) if row: if aggregate_type == 'count': value, std_unit_system = row else: magnitude, direction, std_unit_system = row value = weeutil.weeutil.to_complex(magnitude, direction) else: std_unit_system = db_manager.std_unit_system value = None else: # The result is more complex, requiring vector arithmetic. We will have to do it # in Python std_unit_system = None xsum = ysum = 0.0 count = 0 select_stmt = WindVec.complex_sql_wind % interpolation_dict for rec in db_manager.genSql(select_stmt, timespan): # Unpack the record mag, direction, unit_system = rec # Ignore rows where magnitude is NULL if mag is None: continue # A good direction is necessary unless the mag is zero: if mag == 0.0 or direction is not None: if std_unit_system: if std_unit_system != unit_system: raise weewx.UnsupportedFeature("Unit type cannot change within a time interval.") else: std_unit_system = unit_system # An undefined direction is OK (and expected) if the magnitude # is zero. But, in that case, it doesn't contribute to the sums either. if direction is None: # Sanity check if weewx.debug: assert (mag == 0.0) else: xsum += mag * math.cos(math.radians(90.0 - direction)) ysum += mag * math.sin(math.radians(90.0 - direction)) count += 1 # We've gone through the whole interval. Were there any good data? if count: # Form the requested aggregation: if aggregate_type == 'sum': value = complex(xsum, ysum) else: # Must be 'avg' value = complex(xsum, ysum) / count else: value = None # Look up the unit type and group of this combination of observation type and aggregation: t, g = weewx.units.getStandardUnitType(std_unit_system, obs_type, aggregate_type) # Form the ValueTuple and return it: return weewx.units.ValueTuple(value, t, g)
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % ( 'MQTT Dashboard ' + MD_VERSION, REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(MdInstaller, self).__init__( version=MD_VERSION, name='MQTT_Dashboard', description='weeWX support for a MQTT based dashboard.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", report_services=[ 'user.mqtt_dashboard.MQTTRealtime', 'user.mqtt_dashboard.MQTTArchive', 'user.mqtt_dashboard.MQTTWU' ], config={ 'MQTTDashboard': { 'MQTT': { 'server_url': 'replace_me' }, 'MQTTRealtime': { 'min_interval': '0', 'additional_binding': 'wx_binding', 'windrun_loop': 'True', 'max_cache_age': '600', 'Calculate': { 'atc': '0.8', 'nfac': '2', 'Algorithm': { 'maxSolarRad': 'RS' } }, 'DecimalPlaces': { 'degree_compass': '******', 'degree_C': '2', 'degree_F': '2', 'foot': '2', 'hPa': '2', 'inch': '3', 'inch_per_hour': '3', 'inHg': '4', 'km': '2', 'km_per_hour': '1', 'mbar': '2', 'meter': '1', 'meter_per_second': '2', 'mile': '2', 'mile_per_hour': '1', 'mm': '2', 'mm_per_hour': '2', 'percent': '1', 'uv_index': '2', 'watt_per_meter_squared': '1', }, 'Groups': { 'group_altitude': 'foot', 'group_pressure': 'hPa', 'group_rain': 'mm', 'group_speed': 'km_per_hour', 'group_temperature': 'degree_C' }, 'MQTT': { 'topic': 'replace_me/realtime' } }, 'MQTTArchive': { 'Formats': { 'degree_C': '%.1f', 'degree_F': '%.1f', 'degree_compass': '******', 'foot': '%.0f', 'hPa': '%.1f', 'inHg': '%.2f', 'inch': '%.2f', 'inch_per_hour': '%.2f', 'km_per_hour': '%.1f', 'km': '%.1f', 'mbar': '%.1f', 'meter': '%.0f', 'meter_per_second': '%.1f', 'mile': '%.1f', 'mile_per_hour': '%.1f', 'mm': '%.1f', 'mm_per_hour': '%.1f', 'percent': '%.0f', 'uv_index': '%.1f', 'watt_per_meter_squared': '%.0f', 'NONE': 'None' }, 'Groups': { 'group_altitude': 'foot', 'group_pressure': 'hPa', 'group_rain': 'mm', 'group_speed': 'km_per_hour', 'group_temperature': 'degree_C' }, 'MQTT': { 'topic': 'replace_me/slow' } }, 'MQTTWU': { 'WU': { 'api_key': '4306891b564ca391', 'forecast_interval': '1800', 'api_lockout_period': '60', 'max_WU_tries': '3', 'location': 'pws:IQUEENSL336', 'conditions_interval': '1800' }, 'MQTT': { 'conditions_topic': 'replace_me/conditions', 'forecast_topic': 'replace_me/forecast' } } } }, files=[('bin/user', ['bin/user/mqtt_dashboard.py', 'bin/user/mqtt_utility.py'])])
import sys import syslog import time import urllib import urllib2 import weewx import weewx.restx import weewx.units import weewx.wxformulas from weeutil.weeutil import to_bool, accumulateLeaves VERSION = '0.3' if weewx.__version__ < '3': raise weewx.UnsupportedFeature( 'weewx 3 is the minimum required, found %s' % weewx.__version__) def log_msg(level, msg): """ Shows a log message :param level: :param msg: """ syslog.syslog(level, 'restx: Skiron: %s' % msg) def log_dbg(msg): """ Shows a log debug message
def get_series(obs_type, timespan, db_manager, aggregate_type=None, aggregate_interval=None): """Get a series, possibly with aggregation, from the main archive database. The general strategy is that if aggregation is asked for, chop the series up into separate chunks, calculating the aggregate for each chunk. Then assemble the results. If no aggregation is called for, just return the data directly out of the database. """ startstamp, stopstamp = timespan start_vec = list() stop_vec = list() data_vec = list() if aggregate_type: # With aggregation unit, unit_group = None, None if aggregate_type == 'cumulative': do_aggregate = 'sum' total = 0 else: do_aggregate = aggregate_type for stamp in weeutil.weeutil.intervalgen(startstamp, stopstamp, aggregate_interval): # Get the aggregate as a ValueTuple agg_vt = get_aggregate(obs_type, stamp, do_aggregate, db_manager) if unit: # It's OK if the unit is unknown (=None). if agg_vt[1] is not None and (unit != agg_vt[1] or unit_group != agg_vt[2]): raise weewx.UnsupportedFeature( "Cannot change unit groups " "within an aggregation.") else: unit, unit_group = agg_vt[1], agg_vt[2] start_vec.append(stamp.start) stop_vec.append(stamp.stop) if aggregate_type == 'cumulative': if agg_vt[0] is not None: total += agg_vt[0] data_vec.append(total) else: data_vec.append(agg_vt[0]) else: # No aggregation sql_str = "SELECT dateTime, %s, usUnits, `interval` FROM %s " \ "WHERE dateTime >= ? AND dateTime <= ?" % (obs_type, db_manager.table_name) std_unit_system = None # Hit the database. It's possible the type is not in the database, so be prepared # to catch a NoColumnError: try: for record in db_manager.genSql(sql_str, (startstamp, stopstamp)): # Unpack the record timestamp, value, unit_system, interval = record if std_unit_system: if std_unit_system != unit_system: raise weewx.UnsupportedFeature( "Unit type cannot change " "within an aggregation interval.") else: std_unit_system = unit_system start_vec.append(timestamp - interval * 60) stop_vec.append(timestamp) data_vec.append(value) except weedb.NoColumnError: # The sql type doesn't exist. Convert to an UnknownType error raise weewx.UnknownType(obs_type) unit, unit_group = weewx.units.getStandardUnitType( std_unit_system, obs_type, aggregate_type) return (ValueTuple(start_vec, 'unix_epoch', 'group_time'), ValueTuple(stop_vec, 'unix_epoch', 'group_time'), ValueTuple(data_vec, unit, unit_group))
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires WeeWX %s or greater, found %s" % (''.join(('GW1000 driver ', GW1000_VERSION)), REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(Gw1000Installer, self).__init__( version=GW1000_VERSION, name='GW1000', description='WeeWX driver for GW1000 WiFi gateway.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", files=[('bin/user', ['bin/user/gw1000.py'])], config={ 'GW1000': { 'driver': 'user.gw1000' }, 'Accumulator': { 'daymaxwind': { 'extractor': 'last' }, 'lightning_distance': { 'extractor': 'last' }, 'lightning_strike_count': { 'extractor': 'sum' }, 'lightning_last_det_time': { 'extractor': 'last' }, 'stormRain': { 'extractor': 'last' }, 'hourRain': { 'extractor': 'last' }, 'dayRain': { 'extractor': 'last' }, 'weekRain': { 'extractor': 'last' }, 'monthRain': { 'extractor': 'last' }, 'yearRain': { 'extractor': 'last' }, 'totalRain': { 'extractor': 'last' }, 'pm2_51_24hav': { 'extractor': 'last' }, 'pm2_52_24hav': { 'extractor': 'last' }, 'pm2_53_24hav': { 'extractor': 'last' }, 'pm2_54_24hav': { 'extractor': 'last' }, 'wh40_batt': { 'extractor': 'last' }, 'wh26_batt': { 'extractor': 'last' }, 'wh25_batt': { 'extractor': 'last' }, 'wh65_batt': { 'extractor': 'last' }, 'wh31_ch1_batt': { 'extractor': 'last' }, 'wh31_ch2_batt': { 'extractor': 'last' }, 'wh31_ch3_batt': { 'extractor': 'last' }, 'wh31_ch4_batt': { 'extractor': 'last' }, 'wh31_ch5_batt': { 'extractor': 'last' }, 'wh31_ch6_batt': { 'extractor': 'last' }, 'wh31_ch7_batt': { 'extractor': 'last' }, 'wh31_ch8_batt': { 'extractor': 'last' }, 'wh41_ch1_batt': { 'extractor': 'last' }, 'wh41_ch2_batt': { 'extractor': 'last' }, 'wh41_ch3_batt': { 'extractor': 'last' }, 'wh41_ch4_batt': { 'extractor': 'last' }, 'wh51_ch1_batt': { 'extractor': 'last' }, 'wh51_ch2_batt': { 'extractor': 'last' }, 'wh51_ch3_batt': { 'extractor': 'last' }, 'wh51_ch4_batt': { 'extractor': 'last' }, 'wh51_ch5_batt': { 'extractor': 'last' }, 'wh51_ch6_batt': { 'extractor': 'last' }, 'wh51_ch7_batt': { 'extractor': 'last' }, 'wh51_ch8_batt': { 'extractor': 'last' }, 'wh51_ch9_batt': { 'extractor': 'last' }, 'wh51_ch10_batt': { 'extractor': 'last' }, 'wh51_ch11_batt': { 'extractor': 'last' }, 'wh51_ch12_batt': { 'extractor': 'last' }, 'wh51_ch13_batt': { 'extractor': 'last' }, 'wh51_ch14_batt': { 'extractor': 'last' }, 'wh51_ch15_batt': { 'extractor': 'last' }, 'wh51_ch16_batt': { 'extractor': 'last' }, 'wh55_ch1_batt': { 'extractor': 'last' }, 'wh55_ch2_batt': { 'extractor': 'last' }, 'wh55_ch3_batt': { 'extractor': 'last' }, 'wh55_ch4_batt': { 'extractor': 'last' }, 'wh57_batt': { 'extractor': 'last' }, 'wh68_batt': { 'extractor': 'last' }, 'ws80_batt': { 'extractor': 'last' } } } )
import weewx import weewx.units import weewx.xtypes from weewx.units import ValueTuple from weeutil.weeutil import timestamp_to_string from weeutil.weeutil import to_bool from weeutil.weeutil import to_int from weewx.engine import StdService log = logging.getLogger(__name__) WEEWX_AIRLINK_VERSION = "1.0" if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 7): raise weewx.UnsupportedFeature( "weewx-airlink requires Python 3.7 or later, found %s.%s" % (sys.version_info[0], sys.version_info[1])) if weewx.__version__ < "4": raise weewx.UnsupportedFeature( "weewx-airlink requires WeeWX 4, found %s" % weewx.__version__) # Set up observation types not in weewx.units weewx.units.USUnits['air_quality_index'] = 'aqi' weewx.units.MetricUnits['air_quality_index'] = 'aqi' weewx.units.MetricWXUnits['air_quality_index'] = 'aqi' weewx.units.USUnits['air_quality_color'] = 'aqi_color' weewx.units.MetricUnits['air_quality_color'] = 'aqi_color' weewx.units.MetricWXUnits['air_quality_color'] = 'aqi_color'
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires WeeWX %s or greater, found %s" % ('WeeWX-WD ' + WEEWX_WD_VERSION, REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(WeewxWdInstaller, self).__init__( version=WEEWX_WD_VERSION, name='WeeWX-WD', description='WeeWX support for Weather Display Live and Carter Lake/Saratoga weather web site templates.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", process_services=['user.wd.WdWXCalculate'], archive_services=['user.wd.WdArchive', 'user.wd.WdSuppArchive'], config={ 'StdReport': { 'wdPWS': { 'enable': 'False', 'skin': 'PWS', 'HTML_ROOT': 'WD', 'Units': { 'Groups': { 'group_pressure': 'hPa', 'group_rain': 'mm', 'group_rainrate': 'mm_per_hour', 'group_speed': 'km_per_hour', 'group_speed2': 'km_per_hour2', 'group_temperature': 'degree_C' }, }, }, 'wdStackedWindRose': { 'skin': 'StackedWindRose', 'enable': 'True', 'HTML_ROOT': 'WD', 'Units': { 'Groups': { 'group_speed': 'km_per_hour', 'group_speed2': 'km_per_hour2' }, 'TimeFormats': { 'date_f': '%d/%m/%Y', 'date_time_f': '%d/%m/%Y %H:%M' }, }, }, 'wdTesttags': { 'skin': 'Testtags', 'enable': 'True', 'HTML_ROOT': 'WD', 'Units': { 'Groups': { 'group_altitude': 'foot', 'group_degree_day': 'degree_C_day', 'group_pressure': 'hPa', 'group_rain': 'mm', 'group_rainrate': 'mm_per_hour', 'group_speed': 'km_per_hour', 'group_speed2': 'km_per_hour2', 'group_temperature': 'degree_C' }, 'TimeFormats': { 'date_f': '%d/%m/%Y', 'date_time_f': '%d/%m/%Y %H:%M' }, }, }, 'wdClientraw': { 'skin': 'Clientraw', 'enable': 'True', 'HTML_ROOT': 'WD', 'Units': { 'StringFormats': { 'degree_C': '%.1f', 'degree_compass': '******', 'foot': '%.0f', 'hPa': '%.1f', 'km': '%.1f', 'knot': '%.1f', 'mm': '%.1f', 'percent': '%.0f', 'uv_index': '%.1f', 'watt_per_meter_squared': '%.0f', 'NONE': '--' }, }, } }, 'DataBindings': { 'wd_binding': { 'database': 'weewxwd_sqlite', 'table_name': 'archive', 'manager': 'weewx.manager.DaySummaryManager', 'schema': 'user.wdschema.weewxwd_schema' }, 'wdsupp_binding': { 'database': 'wd_supp_sqlite', 'table_name': 'supp', 'manager': 'weewx.manager.Manager', 'schema': 'user.wdschema.wdsupp_schema' } }, 'Databases': { 'weewxwd_sqlite': { 'database_type': 'SQLite', 'database_name': 'weewxwd.sdb' }, 'wd_supp_sqlite': { 'database_type': 'SQLite', 'database_name': 'wdsupp.sdb' }, 'weewxwd_mysql': { 'database_type': 'MySQL', 'database_name': 'weewxwd' }, 'wd_supp_mysql': { 'database_type': 'MySQL', 'database_name': 'wdsupp' } }, 'Weewx-WD': { 'data_binding': 'wd_binding', 'sunshine_threshold': '120', 'Supplementary': { 'data_binding': 'wdsupp_binding', 'WU': { 'api_key': 'replace_me', 'enable': 'False' }, 'DS': { 'api_key': 'replace_me', 'enable': 'False' }, 'File': { 'file': '/path/and/filename', 'enable': 'False' } } } }, files=[('bin/user', ['bin/user/stackedwindrose.py', 'bin/user/wdastro.py', 'bin/user/wdschema.py', 'bin/user/wdsearchlist.py', 'bin/user/wdtaggedstats.py', 'bin/user/wd.py']), ('skins/Clientraw', ['skins/Clientraw/clientraw.txt.tmpl', 'skins/Clientraw/clientrawdaily.txt.tmpl', 'skins/Clientraw/clientrawextra.txt.tmpl', 'skins/Clientraw/clientrawhour.txt.tmpl', 'skins/Clientraw/skin.conf']), ('skins/PWS', ['skins/PWS/weewx_pws.xml.tmpl', 'skins/PWS/skin.conf']), ('skins/StackedWindRose', ['skins/StackedWindRose/skin.conf']), ('skins/Testtags', ['skins/Testtags/skin.conf', 'skins/Testtags/testtags.php.tmpl']), ] )
from distutils.version import StrictVersion import sys import syslog import urllib import urllib2 import weewx import weewx.restx import weewx.units from weeutil.weeutil import to_bool, accumulateLeaves VERSION = "0.7" REQUIRED_WEEWX = "3.5.0" if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_WEEWX): raise weewx.UnsupportedFeature("weewx %s or greater is required, found %s" % (REQUIRED_WEEWX, weewx.__version__)) def logmsg(level, msg): syslog.syslog(level, 'restx: Influx: %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) # some unit labels are rather lengthy. this reduces them to something shorter. UNIT_REDUCTIONS = {
import weeutil import weewx import weewx.drivers import weewx.units import weewx.wxformulas from weeutil.weeutil import ListOfDicts DRIVER_NAME = 'XmlParse' DRIVER_VERSION = '0.1.0' SUPPORTED_TIMEZONES = ('GMT', 'UTC') CONV_FUNCS = ListOfDicts({'Degrees F': weewx.units.FtoC, 'km/h': weewx.units.conversionDict['km_per_hour']['meter_per_second'], 'hPa': weewx.units.conversionDict['hPa']['mbar']}) if weewx.__version__ < "3": raise weewx.UnsupportedFeature("WeeWX 3.x or greater is required, found %s" % weewx.__version__) class MissingOption(StandardError): """Exception thrown when a mandatory option is invalid or otherwise has not been included in a config stanza.""" def logmsg(dst, msg): syslog.syslog(dst, 'xmlparse: %s' % msg) def logdbg(msg): logmsg(syslog.LOG_DEBUG, msg)
from urllib.parse import urlencode except ImportError: # Python 2 from urllib import urlencode import re import sys import time import weewx import weewx.restx import weewx.units VERSION = "0.1" if weewx.__version__ < "3": raise weewx.UnsupportedFeature("WeeWX 3 es requerido, usted tiene %s" % weewx.__version__) try: # Test for new-style weewx logging by trying to import weeutil.logger import weeutil.logger import logging log = logging.getLogger(__name__) def logdbg(msg): log.debug(msg) def loginf(msg): log.info(msg) def logerr(msg): log.error(msg)
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % (''.join( 'SteelSeries Weather Gauges ', SSWG_VERSION), REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(SswgInstaller, self).__init__( version=SSWG_VERSION, name='SteelSeries', description='A weeWX extension for the SteelSeries Weather Gauges.', author= "Packaged by Gary Roderick, SteelSeries gauges by Gerrit Grunwald, Weather Gauges scripts by Mark Crossley and weeWX skin by Matthew Wall", author_email="gjroderick<@>gmail.com", config={ 'StdReport': { 'SteelSeries': { 'skin': 'ss', 'HTML_ROOT': 'ss', 'Units': { 'Groups': { 'group_altitude': 'foot', # foot or meter 'group_pressure': 'hPa', # hPa, inHg or mbar 'group_rain': 'mm', # mm or inch 'group_rainRate': 'mm_per_hour', # mm_per_hour or inch_per_hour 'group_speed': 'km_per_hour', # km_per_hour, mile_per_hour, # meter_per_second or knot 'group_temperature': 'degree_C' # degree_C or degree_F }, 'StringFormats': { 'degree_C': '%.1f', 'degree_F': '%.1f', 'degree_compass': '******', 'foot': '%.0f', 'hPa': '%.1f', 'inHg': '%.3f', 'inch': '%.2f', 'inch_per_hour': '%.2f', 'km': '%.1f', 'km_per_hour': '%.0f', 'knot': '%.0f', 'mbar': '%.1f', 'meter': '%.0f', 'meter_per_second': '%.1f', 'mile': '%.1f', 'mile_per_hour': '%.0f', 'mm': '%.1f', 'mmHg': '%.1f', 'mm_per_hour': '%.1f', 'percent': '%.0f', 'uv_index': '%.1f', 'watt_per_meter_squared': '%.0f' } } } } }, files=[('skins/ss', [ 'skins/ss/gauge-data.txt.tmpl', 'skins/ss/index.html.tmpl', 'skins/ss/skin.conf', 'skins/ss/scripts/gauges.js', 'skins/ss/scripts/language.min.js', 'skins/ss/scripts/RGraph.common.core.min.js', 'skins/ss/scripts/RGraph.rose.min.js', 'skins/ss/scripts/steelseries_tween.min.js', 'skins/ss/css/gauges-ss.css' ])])
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires weeWX %s or greater, found %s" % (''.join(('StackedWindRose ', IMAGESTACKEDWINDROSE_VERSION)), REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(StackedWindRoseInstaller, self).__init__( version="2.1.0", name='StackedWindRose', description='Stacked windrose image generator for weeWX.', author="Gary Roderick", author_email="*****@*****.**", config={ 'StdReport': { 'StackedWindRose': { 'skin': 'StackedWindRose', 'Units': { 'Groups': { 'group_speed': 'km_per_hour' }, 'Labels': { 'km_per_hour': 'km/h', 'knot': 'knots', 'meter_per_second': 'm/s', 'mile_per_hour': 'mph' }, }, 'Labels': { 'compass_points': ['N', 'S', 'E', 'W'], 'Generic': { 'windGust': 'Gust Speed', 'windSpeed': 'Wind Speed' } }, 'ImageStackedWindRoseGenerator': { 'image_background_image': 'None', 'image_width': '382', 'image_height': '361', 'image_background_circle_color': '0xF5F5F5', 'image_background_box_color': '0xF5C696', 'image_background_range_ring_color': '0xC3D9DD', 'windrose_plot_border': '5', 'windrose_legend_bar_width': '10', 'windrose_font_path': '/usr/share/fonts/truetype/freefont/FreeSansBold.ttf', 'windrose_plot_font_size': '10', 'windrose_plot_font_color': '0x000000', 'windrose_legend_font_size': '10', 'windrose_legend_font_color': '0x000000', 'windrose_label_font_size': '12', 'windrose_label_font_color': '0x000000', 'windrose_plot_petal_colors': ['aqua', '0xFF9900', '0xFF3300', '0x009900', '0x00CC00', '0x33FF33', '0x00FFCC'], 'windrose_plot_petal_width': '16', 'day_images': { 'period': '86400', 'daywindrose': { 'format': 'png', 'windSpeed': { 'label': '24 Hour Wind Rose', 'time_stamp': '%H:%M %-d %b %y', 'time_stamp_location': ['bottom', 'right'] } } } } } } }, files=[ ('bin/user', ['bin/user/imageStackedWindRose.py']), ('skins/StackedWindRose', ['skins/StackedWindRose/skin.conf']) ] )
# log_traceback() generates the same output but the signature and code is # different between v3 and v4. We only need log_traceback at the log.error # level so define a suitable wrapper function. def log_traceback_error(prefix=''): log_traceback(prefix=prefix, loglevel=syslog.LOG_ERR) APRX_VERSION = "0.2.1" REQUIRED_WEEWX_VERSION = "3.0.0" if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_WEEWX_VERSION): msg = "%s requires WeeWX %s or greater, found %s" % (''.join(('WeeWX APRX ', APRX_VERSION)), REQUIRED_WEEWX_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) def convert(v, obs, group, from_unit_system, to_units): """Convert an observation value to the required units.""" # get the units used by our observation given the packet unit system ut = weewx.units.getStandardUnitType(from_unit_system, obs) # express our observation as a ValueTuple vt = weewx.units.ValueTuple(v, ut[0], group) # return the value return weewx.units.convert(vt, to_units).value def nullproof(key, data): """Replace a missing or None value packet field with 0."""
import syslog import time import weeutil.weeutil import weewx import weewx.engine import weewx.manager from weewx.engine import StdService VERSION = "0.4.1-lh" # # 2015-12-28 Modified by Luc Heijst to work with weewx version 3.3.1 # if weewx.__version__ < "3": raise weewx.UnsupportedFeature("weewx 3 is required, found %s" % weewx.__version__) schema = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'), ('usUnits', 'INTEGER NOT NULL'), ('interval', 'INTEGER NOT NULL'), ('pressure', 'REAL'), ('inTemp', 'REAL'), ('outTemp', 'REAL'), ('outHumidity', 'REAL'), ('windSpeed', 'REAL'), ('windDir', 'INTEGER'), ('deltarain', 'REAL'), ('geiger', 'INTEGER'), ('downfall', 'VARCHAR(5)'), ('illumination', 'INTEGER'), ('long_term_geiger', 'INTEGER'), ('long_term_rain', 'REAL'), ('maxWind', 'REAL')] def get_default_binding_dict(): return { 'database': 'raw_mysql', 'manager': 'weewx.manager.Manager',
def __init__(self): if StrictVersion(weewx.__version__) < StrictVersion(REQUIRED_VERSION): msg = "%s requires WeeWX %s or greater, found %s" % ( 'Hfw ' + HFW_VERSION, REQUIRED_VERSION, weewx.__version__) raise weewx.UnsupportedFeature(msg) super(HfwInstaller, self).__init__( version=HFW_VERSION, name='Hfw', description= 'WeeWX support for plotting observational data using Highcharts.', author="Gary Roderick", author_email="gjroderick<@>gmail.com", config={ 'StdReport': { 'Highcharts': { 'skin': 'Highcharts', 'CheetahGenerator': { 'ToDate': { 'YearJSON': { 'stale_age': '3600' } } }, 'Units': { 'Groups': { 'group_altitude': 'meter', 'group_degree_day': 'degree_C_day', 'group_pressure': 'hPa', 'group_rain': 'mm', 'group_rainrate': 'mm_per_hour', 'group_speed': 'km_per_hour', 'group_speed2': 'km_per_hour2', 'group_temperature': 'degree_C' }, 'StringFormats': { 'centibar': '%.0f', 'cm': '%.2f', 'cm_per_hour': '%.2f', 'degree_C': '%.1f', 'degree_F': '%.1f', 'degree_compass': '******', 'foot': '%.0f', 'hPa': '%.1f', 'inHg': '%.3f', 'inch': '%.2f', 'inch_per_hour': '%.2f', 'km_per_hour': '%.0f', 'km_per_hour2': '%.1f', 'knot': '%.0f', 'knot2': '%.1f', 'mbar': '%.1f', 'meter': '%.0f', 'meter_per_second': '%.1f', 'meter_per_second2': '%.1f', 'mile_per_hour': '%.0f', 'mile_per_hour2': '%.1f', 'mm': '%.1f', 'mmHg': '%.1f', 'mm_per_hour': '%.1f', 'percent': '%.0f', 'uv_index': '%.1f', 'volt': '%.1f', 'watt_per_meter_squared': '%.0f', 'NONE': 'N/A' }, 'Labels': { 'centibar': 'cb', 'cm': 'cm', 'cm_per_hour': 'cm/hr', 'degree_C': '\u00B0 C', 'degree_F': '\u00B0 F', 'degree_compass': '******', 'foot': 'feet', 'hPa': 'hPa', 'inHg': 'inHg', 'inch': 'in', 'inch_per_hour': 'in/hr', 'km_per_hour': 'km/hr', 'km_per_hour2': 'km/hr', 'knot': 'knots', 'knot2': 'knots', 'mbar': 'mbar', 'meter': 'meters', 'meter_per_second': 'm/s', 'meter_per_second2': 'm/s', 'mile_per_hour': 'mph', 'mile_per_hour2': 'mph', 'mm': 'mm', 'mmHg': 'mmHg', 'mm_per_hour': 'mm/hr', 'percent': '%', 'uv_index': 'Index', 'volt': 'V', 'watt_per_meter_squared': 'W/m\u00B2', 'NONE': '' } }, 'Extras': { 'MinRange': { 'outTemp': [10, 'degree_C'], 'windchill': [10, 'degree_C'], 'barometer': [20, 'hPa'], 'windSpeed': '10', 'rain': [5, 'mm'], 'radiation': '500', 'UV': '16' }, 'WindRose': { 'title': 'Wind Rose', 'source': 'windSpeed', 'period': [86400, 604800, 'month', 'year'], 'aggregate_type': '', 'aggregate_interval': '', 'petals': '16', 'petal_colors': [ 'aqua', '0x0099FF', '0x0033FF', '0x009900', '0x00CC00', '0x33FF33', '0xCCFF00' ], 'speedfactor': [ '0.0', '0.1', '0.2', '0.3', '0.5', '0.7', '1.0' ], 'show_legend_title': 'True', 'show_band_percent': 'True', 'bullseye_percent': 'True', 'precision': '1', 'bullseye_size': '20', 'bullseye_color': '0xFFFACD', 'calm_limit': '0.5' } } } } }, files=[('bin/user', ['bin/user/highchartssearchlist.py']), ('skins/Highcharts', [ 'skins/Highcharts/json/week.json.tmpl', 'skins/Highcharts/json/year.json.tmpl', 'skins/Highcharts/skin.conf' ])])