Skip to content

Commit

Permalink
Merge pull request #166 from brewster76/4.3
Browse files Browse the repository at this point in the history
4.3
  • Loading branch information
mKainzbauer authored Dec 8, 2024
2 parents 3ee2746 + 830256b commit 1e09e50
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 154 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ Available in multiple languages. Help wanted! We need help with translations for

Read the upgrading guides in the wiki, if you already have an older version installed: https://github.com/brewster76/fuzzy-archer/wiki

New in v4.3:

- Upgraded dependencies
- WeeWX 5.1 and above supports configuration of an individual locale for each report
- Fixed issues
- https://github.com/brewster76/fuzzy-archer/issues/137
- https://github.com/brewster76/fuzzy-archer/issues/140
- https://github.com/brewster76/fuzzy-archer/issues/141
- https://github.com/brewster76/fuzzy-archer/issues/143
- https://github.com/brewster76/fuzzy-archer/issues/146
- https://github.com/brewster76/fuzzy-archer/issues/144
- https://github.com/brewster76/fuzzy-archer/issues/152
- https://github.com/brewster76/fuzzy-archer/issues/153
- https://github.com/brewster76/fuzzy-archer/issues/154
- New norwegian translation (thx to @[Aslak Vaa](https://github.com/aslak47))
- Added feature to configure gauge needle behaviour with null or missing data (thx to @[claudobahn](https://github.com/claudobahn))
- New default symbol for shipped lightning chart.
- symbolSize is configurable, even with a JS function (see shipped lightning chart configs)
- Other smaller fixes

Change list: https://github.com/brewster76/fuzzy-archer/compare/v4.2...4.3

New in v4.2:

- Upgraded dependencies
Expand Down
2 changes: 1 addition & 1 deletion bin/user/historygenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def __init__(self, generator):
self.cache_time = 0

self.search_list_extension = {}
self.search_list_extension['fuzzy_archer_version'] = generator.config_dict['fuzzy_archer_version']
self.search_list_extension['fuzzy_archer_version'] = generator.skin_dict['version']

# Make some config available to templates
self.add_to_extension_list('Navigation', generator.skin_dict)
Expand Down
155 changes: 92 additions & 63 deletions bin/user/jsonengine.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@
TODO: example
"""
import sys
import time
import logging
import json
import os.path

import weewx.reportengine
import weewx.xtypes

try:
from weeutil.weeutil import accumulateLeaves
Expand All @@ -37,6 +37,8 @@
from weeutil.config import merge_config
from weewx.units import convert
from weeutil.weeutil import to_bool
from weeutil.weeutil import TimeSpan
from datetime import datetime, time, timedelta
from user.sunevents import SunEvents


Expand Down Expand Up @@ -103,7 +105,7 @@ def setup(self):
self.record_dict_vtd[key] = None

def gen_data(self):
start_time = time.time()
start_time = datetime.now().timestamp()
ngen = 0
unit_systems = {'US': weewx.units.USUnits, 'METRIC': weewx.units.MetricUnits, 'METRICWX': weewx.units.MetricWXUnits}
source_unit_system = self.config_dict['StdConvert']['target_unit']
Expand All @@ -119,33 +121,33 @@ def gen_data(self):
self.frontend_data['units'] = self.units_dict
self.frontend_data['labels'] = self.labels_dict
live_options = accumulateLeaves(self.json_dict)
duration = int(live_options.get('timespan'))
first_value_timestamp = self.lastGoodStamp - duration * 60 * 60
last_value_timestamp = self.lastGoodStamp
self.first_timestamp = first_value_timestamp

for gauge in self.gauge_dict.sections:
data_type = self.gauge_dict[gauge].get('data_type', gauge)
ret, gauge_history = self.gen_history_data(gauge, data_type, live_options, self.gauge_dict[gauge].get('data_binding', None), None)
self.frontend_data['gauges'][gauge]['target_unit'] = self.get_target_unit(gauge)
self.frontend_data['gauges'][gauge]['obs_group'] = self.get_obs_group(gauge)

if ret is not None:
ngen += 1
log.debug("Adding %s to frontend_data." % gauge)
self.frontend_data[gauge] = gauge_history
for chart in self.chart_dict.sections:
for category in self.chart_dict[chart].sections:
data_type = self.chart_dict[chart][category].get('data_type', category)
plotType = self.chart_dict[chart][category].get('plotType', 'line')
ret, category_history = self.gen_history_data(category, data_type, live_options, self.chart_dict[chart][category].get('data_binding'), plotType)
self.frontend_data['charts'][chart][category]['target_unit'] = self.get_target_unit(category)
self.frontend_data['charts'][chart][category]['obs_group'] = self.get_obs_group(category)
category_config = self.frontend_data['charts'][chart][category]
ret, category_history, daily_highlow_values = self.gen_history_data(category, category_config, self.chart_dict[chart][category].get('data_binding'))
category_config['target_unit'] = self.get_target_unit(category)
category_config['obs_group'] = self.get_obs_group(category)

if ret is not None:
ngen += 1
log.debug("Adding %s to frontend_data." % category)
self.frontend_data[category] = category_history
self.frontend_data[category + "_daily_high_low"] = daily_highlow_values
for gauge in self.gauge_dict.sections:
gauge_config = self.frontend_data['gauges'][gauge]
ret, gauge_history = self.gen_history_data(gauge, gauge_config, self.gauge_dict[gauge].get('data_binding'))
gauge_config['target_unit'] = self.get_target_unit(gauge)
gauge_config['obs_group'] = self.get_obs_group(gauge)

timespan = int(live_options.get('timespan'))
first_value_timestamp = self.lastGoodStamp - timespan * 60 * 60
last_value_timestamp = self.lastGoodStamp
if ret is not None:
ngen += 1
log.debug("Adding %s to frontend_data." % gauge)
self.frontend_data[gauge] = gauge_history

altitude = self.config_dict['Station']['altitude']
altitude_m = altitude[0]
Expand All @@ -164,7 +166,7 @@ def gen_data(self):
self.write_json(os.path.join(html_root, data_filename))
self.write_ts_file(os.path.join(html_root, timestamp_filename))

finish_time = time.time()
finish_time = datetime.now().timestamp()

log.info("JSONGenerator: Generated %d data items for %s in %.2f seconds" %
(ngen, self.skin_dict['REPORT_NAME'], finish_time - start_time))
Expand All @@ -183,65 +185,47 @@ def get_obs_group(self, column_name):
log.info("JSONGenerator: weewx.units.obs_group_dict['%s'] is not present, using the empty string." % column_name)
return ""

def gen_history_data(self, obs_name, column_name, live_options, binding_name, plotType):
def gen_history_data(self, obs_name, item_config, binding_name):

column_name = item_config.get('data_type', obs_name)
log.debug("Generating history for obs_name %s and column_name %s with binding %s" % (obs_name, column_name, binding_name))

if obs_name in self.frontend_data:
log.debug("Data for observation %s has already been collected." % obs_name)
return None, None
# Find display unit of measure
try:
target_unit = self.get_target_unit(column_name)
except:
log.info("JSONGenerator: *** Could not find target unit of measure for column '%s' ***" % column_name)
return 0, None
try:
timespan = int(live_options.get('timespan'))
except:
logging.exception("Error getting timespan:")
else:
history_list = []
time_list = []

try:
if binding_name:
db_manager = self.db_binder.get_manager(binding_name)
else:
db_manager = self.db_binder.get_manager()

except:
if binding_name:
logging.exception("Could not get db_manager for binding %s" % binding_name)
else:
logging.exception("Could not get db_manager for default binding")

batch_records = db_manager.genBatchRecords(self.lastGoodStamp - timespan * 60 * 60, self.lastGoodStamp)

for rec in batch_records:
try:
db_value_tuple = weewx.units.as_value_tuple(rec, column_name)
except:
log.debug("JSONGenerator: Ignoring data for column '%s', is this column in the database table?" % (column_name))
return 0, None

if target_unit == "":
history_value = rec[column_name]
else:
history_value = weewx.units.convert(db_value_tuple, target_unit)[0]
try:
if history_value is None:
history_list.append(history_value)
else:
history_list.append(float(history_value))
time_list.append(rec['dateTime'] * 1000)
except:
log.debug("JSONGenerator: Cannot decode reading of '%s' for column '%s'" % (history_value, column_name))




# Find display unit of measure
try:
target_unit = self.get_target_unit(column_name)
except:
log.info("JSONGenerator: *** Could not find target unit of measure for column '%s' ***" % column_name)
return 0, None

log.debug("returning history list")
return 1, list(zip(time_list, history_list))
aggregate_types = []
if item_config.get('showMaxMarkPoint', 'false') == 'true':
aggregate_types.append("max")
if item_config.get('showMinMarkPoint', 'false') == 'true':
aggregate_types.append("min")

timespan = TimeSpan(self.first_timestamp, self.lastGoodStamp)
series = weewx.xtypes.get_series(column_name, timespan, db_manager)
daily_highlow_values = []
for aggregate_type in aggregate_types:
daily_highlow_values.append(self.get_daily_highlow_values(column_name, aggregate_type, self.first_timestamp, self.lastGoodStamp, db_manager))
combined_series, processed_highlow_values = self.combine_series(series, daily_highlow_values, item_config, target_unit)
log.debug("Returning data series for '%s'" % column_name)
return 1, combined_series, processed_highlow_values

def write_json(self, data_filename):

Expand Down Expand Up @@ -279,3 +263,48 @@ def get_day_night_events(self, start, end, lon, lat, altitude_m):
darkening_extent = 1
event[1] = darkening_extent
return events

def combine_series(self, series, daily_highlow_values, item_config, target_unit):

decimals = int(item_config.get('decimals', '3'))
combined_series = []
processed_highlow_values = []
for index, interval_start_time in enumerate(series[0][0]):
interval_end_time = series[1][0][index]
value = series[2][0][index]
if value is not None:
value = self.convert_value(value, decimals, series[2].unit, series[2].group, target_unit)
for highlow_values in daily_highlow_values:
for highlow_value in highlow_values:
highlow_time = highlow_value[0]
if highlow_time is not None and highlow_time > interval_start_time and highlow_time <= interval_end_time:
if highlow_time <= interval_end_time:
processed_value = [highlow_time * 1000, self.convert_value(highlow_value[1], decimals, series[2].unit, series[2].group, target_unit)]
combined_series.append(processed_value)
processed_value.append(highlow_value[2])
processed_highlow_values.append(processed_value)
else:
value = highlow_value[1]
combined_series.append([interval_end_time * 1000, value])
return combined_series, processed_highlow_values

def convert_value(self, value, decimals, source_unit, source_group, target_unit):
if target_unit != "":
value_tuple = {0: value, 1: source_unit, 2: source_group}
value = weewx.units.convert(value_tuple, target_unit)[0]

return round(float(value), decimals + 1)

def get_daily_highlow_values(self, obs_type, aggregate_type, start_time, end_time, db_manager):
value_list = []
start_of_day = datetime.combine(datetime.fromtimestamp(start_time), time.min)
while start_of_day.timestamp() < end_time:
start_of_next_day = start_of_day + timedelta(days=1)
timespan = TimeSpan(start_of_day.timestamp(), start_of_next_day.timestamp())
highlow_value = weewx.xtypes.get_aggregate(obs_type, timespan, aggregate_type, db_manager)[0]
highlow_time = weewx.xtypes.get_aggregate(obs_type, timespan, aggregate_type + "time", db_manager)[0]
value_list.append([highlow_time, highlow_value, aggregate_type])

start_of_day = start_of_next_day

return value_list
3 changes: 1 addition & 2 deletions install.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,14 @@ def __init__(self):
'skins/Bootstrap/lang/th.conf',
'skins/Bootstrap/lang/zh.conf'])]

version="4.2"
version="4.3"
super(BootstrapInstaller, self).__init__(
version=version,
name='bootstrap',
description='A skin based around the bootstrap framework',
author="Nick Dajda, Michael Kainzbauer and other contributors",
author_email="[email protected]",
config={
'fuzzy_archer_version':version,
'StdReport': {
'Bootstrap': {
'skin':'Bootstrap',
Expand Down
6 changes: 3 additions & 3 deletions skins/Bootstrap/css/bootstrap-icons.min.css

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions skins/Bootstrap/css/bootstrap.min.css

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions skins/Bootstrap/js/bootstrap.bundle.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit 1e09e50

Please sign in to comment.