>From the logs, it looks like there are some temperature values missing in
your database (that's where the NoneType came from). Like your station
stopped working for 2 or 3 days!?
I added a check to address this issue. Could you please replace
/usr/share/weewx/user/stats_util.py with the attached stats_util.py?
Any chance I could get a copy of your weewx database to test and verify
this?
For reference: I also added a issue on GH for
this: https://github.com/Daveiano/weewx-wdc/issues/9
[email protected] schrieb am Samstag, 28. Mai 2022 um 18:38:07 UTC+2:
> The skin displays but there are quite a bit of errors (see below).
>
> May 28 12:35:16 raspberrypi weewx[8931] INFO weewx.manager: Added record
> 2022-05-28 12:35:00 EDT (1653755700) to database 'weewx.sdb'
> May 28 12:35:16 raspberrypi weewx[8931] INFO weewx.manager: Added record
> 2022-05-28 12:35:00 EDT (1653755700) to daily summary in 'weewx.sdb'
> May 28 12:35:20 raspberrypi weewx[8931] INFO weewx.cheetahgenerator:
> Generated 8 files for report SeasonsReport in 1.54 seconds
> May 28 12:35:21 raspberrypi weewx[8931] INFO weewx.imagegenerator:
> Generated 15 images for report SeasonsReport in 0.95 seconds
> May 28 12:35:21 raspberrypi weewx[8931] INFO weewx.reportengine: Copied 0
> files to /var/www/html/weewx
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator:
> Evaluation of template /etc/weewx/skins/weewx-wdc/year-%Y.html.tmpl failed
> with exception '<class 'TypeError'>'
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> Ignoring template /etc/weewx/skins/weewx-wdc/year-%Y.html.tmpl
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> Reason: '>=' not supported between instances of 'NoneType' and 'float'
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> Traceback (most recent call last):
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "/usr/share/weewx/weewx/cheetahgenerator.py", line 348, in generate
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> unicode_string = compiled_template.respond()
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "_etc_weewx_skins_weewx_wdc_year__Y_html_tmpl.py", line 183, in
> respond
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "/usr/lib/python3/dist-packages/Cheetah/Template.py", line 1707, in
> _handleCheetahInclude
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> self._CHEETAH__cheetahIncludes[_includeID].respond(trans)
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "_etc_weewx_skins_weewx_wdc_includes_climatological_days_inc.py",
> line 277, in respond
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "_etc_weewx_skins_weewx_wdc_includes_climatological_days_inc.py",
> line 106, in __errorCatcher6
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "<string>", line 1, in <module>
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "/usr/share/weewx/user/stats_util.py", line 175, in
> get_climatological_day
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> return len(list(days))
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "/usr/share/weewx/user/stats_util.py", line 173, in <lambda>
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> days = filter(lambda x: x.raw >= value, list(day_series.data))
> May 28 12:35:23 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> TypeError: '>=' not supported between instances of 'NoneType' and 'float'
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator:
> Evaluation of template /etc/weewx/skins/weewx-wdc/statistics.html.tmpl
> failed with exception '<class 'TypeError'>'
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> Ignoring template /etc/weewx/skins/weewx-wdc/statistics.html.tmpl
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> Reason: '>=' not supported between instances of 'NoneType' and 'float'
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> Traceback (most recent call last):
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "/usr/share/weewx/weewx/cheetahgenerator.py", line 348, in generate
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> unicode_string = compiled_template.respond()
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "_etc_weewx_skins_weewx_wdc_statistics_html_tmpl.py", line 191, in
> respond
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "/usr/lib/python3/dist-packages/Cheetah/Template.py", line 1707, in
> _handleCheetahInclude
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> self._CHEETAH__cheetahIncludes[_includeID].respond(trans)
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "_etc_weewx_skins_weewx_wdc_includes_climatological_days_inc.py",
> line 277, in respond
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "_etc_weewx_skins_weewx_wdc_includes_climatological_days_inc.py",
> line 106, in __errorCatcher6
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "<string>", line 1, in <module>
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "/usr/share/weewx/user/stats_util.py", line 175, in
> get_climatological_day
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> return len(list(days))
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> File "/usr/share/weewx/user/stats_util.py", line 173, in <lambda>
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> days = filter(lambda x: x.raw >= value, list(day_series.data))
> May 28 12:35:35 raspberrypi weewx[8931] ERROR weewx.cheetahgenerator: ****
> TypeError: '>=' not supported between instances of 'NoneType' and 'float'
> May 28 12:35:35 raspberrypi weewx[8931] INFO weewx.cheetahgenerator:
> Generated 9 files for report WdcReport in 14.05 seconds
> May 28 12:35:35 raspberrypi weewx[8931] INFO weewx.reportengine: Copied 0
> files to /var/www/html/weewx/wdc
>
> On Friday, May 27, 2022 at 8:25:38 PM UTC-4 [email protected] wrote:
>
>> Yes, that's correct, I think weewx wants the zip to contain only one
>> folder which contains the whole extension. (if you want to directly install
>> from zip without the "extract to folder" step)
>>
>> Glad I could help you!
>>
>> [email protected] schrieb am Samstag, 28. Mai 2022 um 02:19:15 UTC+2:
>>
>>> Got it working. I see it can't install from zip. Need to extract to
>>> directory and install from that location. Thank you.
>>>
>>> On Friday, May 27, 2022 at 5:31:53 PM UTC-4 [email protected] wrote:
>>>
>>>> The file location is correct, but you need to use the .zip which is
>>>> attached to a release.
>>>>
>>>> The latest release is v1.2.0, the download path for the zip is
>>>> https://github.com/Daveiano/weewx-wdc/releases/download/v1.2.0/weewx-wdc-v1.2.0.zip
>>>> Release page is here:
>>>> https://github.com/Daveiano/weewx-wdc/releases/tag/v1.2.0 (its the
>>>> first linked zip)
>>>>
>>>> *Background*: The files in the src/ directory are the Source files
>>>> (TypeScript, SCSS). When creating a release, the source files get
>>>> transformed and optimized, the output location of these transformed files
>>>> is the location from the install.py. The release.zip should contain all
>>>> these transformed files (like service-worker.js), but if you download the
>>>> current state of the repo, these files are not included, hence the error.
>>>>
>>>> Please let me know if this helps and solves the problem, I will also
>>>> add a notice about it on the readme page.
>>>>
>>>> [email protected] schrieb am Freitag, 27. Mai 2022 um 14:30:21 UTC+2:
>>>>
>>>>> Trying to install from zip (also tried from tar.gz) and getting the
>>>>> following:
>>>>>
>>>>> "sudo wee_extension --install=weewx-wdc.zip
>>>>> Request to install 'weewx-wdc.zip'
>>>>> Extracting from zip archive weewx-wdc.zip
>>>>> Traceback (most recent call last):
>>>>> File "/usr/share/weewx/wee_extension", line 92, in <module>
>>>>> main()
>>>>> File "/usr/share/weewx/wee_extension", line 84, in main
>>>>> ext.install_extension(options.install)
>>>>> File "/usr/share/weewx/weecfg/extension.py", line 130, in
>>>>> install_extension
>>>>> self.install_from_dir(extension_dir)
>>>>> File "/usr/share/weewx/weecfg/extension.py", line 183, in
>>>>> install_from_dir
>>>>> shutil.copy(source_path, destination_path)
>>>>> File "/usr/lib/python3.7/shutil.py", line 245, in copy
>>>>> copyfile(src, dst, follow_symlinks=follow_symlinks)
>>>>> File "/usr/lib/python3.7/shutil.py", line 120, in copyfile
>>>>> with open(src, 'rb') as fsrc:
>>>>> FileNotFoundError: [Errno 2] No such file or directory:
>>>>> '/var/tmp/weewx-wdc-1.2.0/skins/weewx-wdc/service-worker.js'
>>>>> "
>>>>>
>>>>> I can see the service-worker.js is located in a different directory
>>>>> than where the install is looking. It is located
>>>>> "weewx-wdc-1.2.0\skins\weewx-wdc\src\js\service-worker.js"
>>>>>
>>>>> On Thursday, May 26, 2022 at 8:49:31 AM UTC-4 [email protected]
>>>>> wrote:
>>>>>
>>>>>> Thank you for your feedback, very appreciated!
>>>>>>
>>>>>> *Is it possible to set custom values for font and graph size, amount
>>>>>> of rows and border size so everything including graphs could be made
>>>>>> visible at a glance without or less scrolling?*
>>>>>> Currently, this is not possible. The skin uses the IBM Carbon Design
>>>>>> System, so these values are more or less predefined. But you are right,
>>>>>> using the space and layouting all the graphs were one of the most
>>>>>> challenging parts of this. I am also not yet 100% happy with it. Perhaps
>>>>>> I
>>>>>> could predefine some "Spacing variations", like a dense one and a wide
>>>>>> one
>>>>>> for example.
>>>>>>
>>>>>> *Any chance for a web version of the weather data center, so one
>>>>>> could publish the visualized csv's to the web? Or even comibne it with
>>>>>> weewx live data in one page? Just a thought*
>>>>>> Do you mean like an export Button on the Desktop Application to
>>>>>> export all data as HTML pages? Well you can also use the WDC Skin with
>>>>>> weewx and import all data to weewx via csv, generate the report and
>>>>>> there
>>>>>> you go ;)
>>>>>> [email protected] schrieb am Donnerstag, 26. Mai 2022 um 12:04:58
>>>>>> UTC+2:
>>>>>>
>>>>>>> Thanks a lot for this skin (and the weather data visualizing app),
>>>>>>> looks very clean!
>>>>>>>
>>>>>>> Is it possible to set custom values for font and graph size, amount
>>>>>>> of rows and border size so everything including graphs could be made
>>>>>>> visible at a glance without or less scrolling?
>>>>>>>
>>>>>>> Any chance for a web version of the weather data center, so one
>>>>>>> could publish the visualized csv's to the web? Or even comibne it with
>>>>>>> weewx live data in one page? Just a thought
>>>>>>> [email protected] schrieb am Samstag, 14. Mai 2022 um 13:13:39
>>>>>>> UTC+2:
>>>>>>>
>>>>>>>> Hi guys!
>>>>>>>>
>>>>>>>> I just wanted to do some advertisement for a new weewx Skin, I
>>>>>>>> developed: https://github.com/Daveiano/weewx-wdc
>>>>>>>>
>>>>>>>> The visual part is based on another weather app, I wrote earlier
>>>>>>>> this year: https://daveiano.github.io/weather-data-center/
>>>>>>>>
>>>>>>>> Please feel free to check it out, a working demo is hosted here:
>>>>>>>> https://www.weewx-hbt.de/
>>>>>>>>
>>>>>>>> Key features included:
>>>>>>>> - Clear and beautiful UI thanks to IBM Carbon and nivo
>>>>>>>> - Configurable Statistic Tiles and Diagram tiles
>>>>>>>> - Combinable diagrams via skin.conf
>>>>>>>> - Responsive
>>>>>>>> - Day, week, month, year and all-time pages
>>>>>>>> - Archive and NOAA Reports
>>>>>>>> - Almanac
>>>>>>>> - Translated for DE and EN
>>>>>>>> - Tabular representation with Carbon Data Tables
>>>>>>>>
>>>>>>>> I consider the skin as feature-complete but I will do some updates
>>>>>>>> in the coming weeks to optimize some things like responsiveness or
>>>>>>>> perhaps
>>>>>>>> add some more statistics.
>>>>>>>>
>>>>>>>> I am a software developer but I never worked with python before. I
>>>>>>>> have been looking for an opportunity to work with python for a long
>>>>>>>> time,
>>>>>>>> so working with weewx and creating a skin did that for me. I am really
>>>>>>>> caught by how things work together in weewx, a great piece of software.
>>>>>>>>
>>>>>>>
--
You received this message because you are subscribed to the Google Groups
"weewx-user" 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-user/8016299e-8795-4847-b29f-b7aaa2260252n%40googlegroups.com.
from weewx.cheetahgenerator import SearchList
from user.diagram_util import DiagramUtil
# Copyright 2022 David Bätge
# Distributed under the terms of the GNU Public License (GPLv3)
class StatsUtil(SearchList):
def get_show_min(self, observation):
"""
Returns if the min stats should be shown.
Args:
observation (string): The observation
Returns:
bool: Show or hide min stat.
"""
show_min_stat = [
"outTemp", "outHumidity", "barometer",
"windDir", "snowDepth", "heatindex",
"dewpoint", "windchill", "cloudbase",
"appTemp"
]
if 'Temp' in observation:
return True
elif 'Humid' in observation:
return True
if observation in show_min_stat:
return True
def get_show_sum(self, observation):
"""
Returns if the sum stats should be shown.
Args:
observation (string): The observation
Returns:
bool: Show or hide sum stat.
"""
show_sum = ["rain", "ET"]
if observation in show_sum:
return True
def get_show_max(self, observation):
"""
Returns if the max stats should be shown.
Args:
observation (string): The observation
Returns:
bool: Show or hide max stat.
"""
show_max = ["rainRate"]
if observation in show_max:
return True
def get_labels(self, prop, precision):
"""
Returns a label like "Todays Max" or "Monthly average.
Args:
prop (string): Min, Max, Sum
precision (string): Day, week, month, year, alltime
Returns:
string: A label.
"""
if precision == 'alltime':
return prop
return prop + ' ' + precision
def get_climatological_day(self, day, period, unit_type, unit_labels):
"""
Return number of days in period for day parameter.
Args:
day (string): Eg. rainDays, hotDays.
period (obj): Period to use, eg. $year, month, $span
unit_type (dict): degree_F or degree_C
Returns:
int: Number of days.
"""
if day == 'iceDays':
day_series = period.outTemp.series(
aggregate_type="max",
aggregate_interval="day",
time_series='start',
time_unit='unix_epoch'
)
days = filter(lambda x: x.raw is not None and x.raw < 0.0, list(day_series.data))
return len(list(days))
if day == 'frostDays':
day_series = period.outTemp.series(
aggregate_type="min",
aggregate_interval="day",
time_series='start',
time_unit='unix_epoch'
)
days = filter(lambda x: x.raw is not None and x.raw < 0.0, list(day_series.data))
return len(list(days))
if day == 'stormDays':
day_series = period.windGust.series(
aggregate_type="max",
aggregate_interval="day",
time_series='start',
time_unit='unix_epoch'
)
if getattr(unit_labels, 'windGust') == ' km/h':
value = 62.0
if getattr(unit_labels, 'windGust') == ' mph':
value = 38.5
if getattr(unit_labels, 'windGust') == ' m/s':
value = 17.2
days = filter(lambda x: x.raw is not None and x.raw >= value, list(day_series.data))
return len(list(days))
if day == 'rainDays':
day_series = period.rain.series(
aggregate_type="sum",
aggregate_interval="day",
time_series='start',
time_unit='unix_epoch'
)
days = filter(lambda x: x.raw is not None and x.raw > 0.0, list(day_series.data))
return len(list(days))
if (day == 'hotDays' or
day == 'summerDays' or
day == 'desertDays' or
day == 'tropicalNights'):
if day == 'tropicalNights':
value = 20.0 if getattr(unit_type, 'outTemp') == 'degree_C' else 68.0
aggregate_type = 'min'
if day == 'summerDays':
value = 25.0 if getattr(unit_type, 'outTemp') == 'degree_C' else 77.0
aggregate_type = 'max'
if day == 'hotDays':
value = 30.0 if getattr(unit_type, 'outTemp') == 'degree_C' else 86.0
aggregate_type = 'max'
if day == 'desertDays':
value = 35.0 if getattr(unit_type, 'outTemp') == 'degree_C' else 95.0
aggregate_type = 'max'
day_series = period.outTemp.series(
aggregate_type=aggregate_type,
aggregate_interval="day",
time_series='start',
time_unit='unix_epoch'
)
days = filter(lambda x: x.raw is not None and x.raw >= value, list(day_series.data))
return len(list(days))
def get_climatological_day_description(self, day, unit_labels,
obs_labels, unit_type):
"""
Return description of day.
Args:
day (string): Eg. rainDays, hotDays.
unit_labels (dict): weewx $unit
obs_labels (obj): weewx $obs.labels
unit_type (dict): degree_F or degree_C
Returns:
string: Day description.
"""
if day == 'iceDays':
value = '0' if getattr(unit_type, 'outTemp') == 'degree_C' else '32'
return obs_labels['outTemp'] + '<sub>max</sub> < ' + value + getattr(unit_labels, 'outTemp')
if day == 'frostDays':
value = '0' if getattr(unit_type, 'outTemp') == 'degree_C' else '32'
return obs_labels['outTemp'] + '<sub>min</sub> < ' + value + getattr(unit_labels, 'outTemp')
if day == 'stormDays':
if getattr(unit_labels, 'windGust') == ' km/h':
value = '62'
if getattr(unit_labels, 'windGust') == ' mph':
value = '38.5'
if getattr(unit_labels, 'windGust') == ' m/s':
value = '17.2'
return obs_labels['windGust'] + ' > ' + value + getattr(unit_labels, 'windGust')
if day == 'rainDays':
return obs_labels['rain'] + ' > 0' + getattr(unit_labels, 'rain')
if (day == 'hotDays' or
day == 'summerDays' or
day == 'desertDays' or
day == 'tropicalNights'):
if day == 'tropicalNights':
value = '20' if getattr(unit_type, 'outTemp') == 'degree_C' else '68'
aggregate_type = 'min'
if day == 'summerDays':
value = '25' if getattr(unit_type, 'outTemp') == 'degree_C' else '77'
aggregate_type = 'max'
if day == 'hotDays':
value = '30' if getattr(unit_type, 'outTemp') == 'degree_C' else '86'
aggregate_type = 'max'
if day == 'desertDays':
value = '35' if getattr(unit_type, 'outTemp') == 'degree_C' else '95'
aggregate_type = 'max'
return obs_labels['outTemp'] + '<sub>' + aggregate_type + '</sub> ≥ ' + value + getattr(unit_labels, 'outTemp')
def get_calendar_color(awlf, obs):
"""
Returns a color for use in diagram.
Args:
observation (string): The observation
Returns:
string: Color string.
"""
if obs == 'rain':
return ['#032c6a', '#02509d', '#1a72b7',
'#4093c7', '#6bb0d7', '#9fcae3'][::-1]
if obs == 'outTemp':
# Warming stripes colors
# @see https://en.wikipedia.org/wiki/Warming_stripes
return ['#032c6a', '#02509d', '#1a72b7', '#4093c7', '#6bb0d7',
'#9fcae3', '#c6dcee', '#dfedf6', '#ffe1d2', '#fcbda3',
'#fc9373', '#fa6a48', '#ee3829', '#cd1116', '#a6060d',
'#660105']
def get_calendar_data(self, obs, aggrgate_type, period):
"""
Returns array of calendar data for use in diagram.
Args:
observation (string): The observation
aggrgate_type (string): Min, max, avg.
period (obj): Period to use, eg. $year, month, $span
Returns:
list: Calendar data.
"""
diagramUtil = DiagramUtil(SearchList)
if obs == 'rain':
day_series = period.rain.series(
aggregate_type=aggrgate_type,
aggregate_interval="day",
time_series='start',
time_unit='unix_epoch'
).round(diagramUtil.get_rounding('rain'))
days = filter(lambda x: x[1].raw > 0.0, list(zip(day_series.start, day_series.data)))
rainDays = []
for day in days:
rainDays.append({
'value': day[1].raw,
'day': day[0].format("%Y-%m-%d")
})
return rainDays
if obs == 'outTemp':
day_series = period.outTemp.series(
aggregate_type=aggrgate_type,
aggregate_interval="day",
time_series='start',
time_unit='unix_epoch'
).round(diagramUtil.get_rounding('rain'))
days = list(zip(day_series.start, day_series.data))
tempDays = []
for day in days:
tempDays.append({
'value': day[1].raw,
'day': day[0].format("%Y-%m-%d")
})
return tempDays