>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 tarob...@gmail.com 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 david....@gmail.com 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! >> >> tarob...@gmail.com 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 david....@gmail.com 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. >>>> >>>> tarob...@gmail.com 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 david....@gmail.com >>>>> 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 ;) >>>>>> f4n...@gmail.com 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 >>>>>>> david....@gmail.com 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 weewx-user+unsubscr...@googlegroups.com. 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