diff options
author | Michael Schantl | 2024-01-19 12:27:33 +0000 |
---|---|---|
committer | Michael Schantl | 2024-01-19 13:56:18 +0000 |
commit | aabfcddf481bb334c832af4f5bcba3bb273edbba (patch) | |
tree | b3af4182d63a24b6ec9ecba33222332792ede6ab | |
parent | 546d0b8165011a7be52e9fee3249524a7b6a54c1 (diff) | |
download | aur-aabfcddf481bb334c832af4f5bcba3bb273edbba.tar.gz |
upgpkg: weewx 5.0.0-1
upstream release
-rw-r--r-- | .SRCINFO | 56 | ||||
-rw-r--r-- | .gitignore | 14 | ||||
-rw-r--r-- | PKGBUILD | 225 | ||||
-rw-r--r-- | genplot.py | 737 | ||||
-rw-r--r-- | pillow-rect.patch | 31 | ||||
-rw-r--r-- | wee_config | 6 | ||||
-rw-r--r-- | wee_database | 6 | ||||
-rw-r--r-- | wee_debug | 6 | ||||
-rw-r--r-- | wee_device | 6 | ||||
-rw-r--r-- | wee_extension | 6 | ||||
-rw-r--r-- | wee_import | 6 | ||||
-rw-r--r-- | wee_reports | 6 | ||||
-rw-r--r-- | weewx-version.patch | 39 | ||||
-rw-r--r-- | weewx.service | 9 | ||||
-rwxr-xr-x | weewx.sysusers | 3 | ||||
-rwxr-xr-x | weewx.tmpfiles | 4 | ||||
-rw-r--r-- | weewxd | 6 | ||||
-rw-r--r-- | wunderfixer | 6 |
18 files changed, 133 insertions, 1039 deletions
@@ -1,49 +1,29 @@ pkgbase = weewx pkgdesc = Software for logging data from weather stations - pkgver = 4.10.2 - pkgrel = 7 + pkgver = 5.0.0 + pkgrel = 1 url = http://www.weewx.com/ arch = any - license = GPL3 + license = GPL-3.0-or-later + makedepends = mkdocs + makedepends = mkdocs-material + makedepends = mkdocs-material-extensions depends = python - depends = python-daemon - depends = python-six + depends = python-cheetah3 depends = python-configobj - depends = python-pyserial depends = python-pillow - depends = python-pyusb - depends = python-cheetah3 - optdepends = python-pyephem: extended almanac information - optdepends = mariadb-clients: MariaDB support - optdepends = python-mysqlclient: MariaDB support + optdepends = python-pyserial: serial port support + optdepends = python-pyusb: USB port support + optdepends = python-pyephem: extended celestial information + optdepends = python-pymysql: MySQL or MariaDB support backup = etc/weewx/weewx.conf - source = weewx-4.10.2.tar.xz::https://github.com/weewx/weewx/archive/refs/tags/v4.10.2.tar.gz - source = wee_config - source = wee_database - source = wee_debug - source = wee_device - source = wee_extension - source = wee_import - source = wee_reports - source = weewxd - source = wunderfixer + source = weewx-5.0.0.tar.xz::https://github.com/weewx/weewx/archive/refs/tags/v5.0.0.tar.gz + source = weewx.sysusers + source = weewx.tmpfiles source = weewx.service - source = genplot.py - source = weewx-version.patch - source = pillow-rect.patch - sha512sums = 8fca9cd7720a29687a0d900e4d89ec2ce5ca5d2aa36bc5b5909ea14ecb849cdbdb6e699cf1c3a0d5505c89ad8c309517db32fd8dc4a0ae4704dfd5ed0cc5747f - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP - sha512sums = SKIP + sha512sums = c3eb23048012f2bab7eac0a25f6dfad4da4ff1591601f7242cf7fec91343e88f3014b7281c021c75cfdbb5b4e73285ab8605325a3c7771e90a5016e3d574dc3b + sha512sums = 6015b870143f6b8ae094b3f94ad53323be8a083f11c177dc508315fb3bbc20dd318124e6ccd41ba9d0388828e18c4b4ae6ce7c4a35ac0cab442eca9e8bbbca2d + sha512sums = 9875bf209439f62fc2e6773b1283a6ed0a2adbe33e7b6461678a5f036679570a98393814eeadcb20b9d9160b79aca0b1a1769eab39be2d1913b64439abd76f62 + sha512sums = 4744fec4faf63b36f9c82a7404e4ecc749eb07e8d90640465ff7a2ae20cdb2560348b0a125467fad215d0e51d88d27a991dc0196899e53d19479dec942d6e52d pkgname = weewx diff --git a/.gitignore b/.gitignore index c40c2f1392b3..40f01e7946ea 100644 --- a/.gitignore +++ b/.gitignore @@ -5,16 +5,6 @@ !.gitignore !PKGBUILD !.SRCINFO -!wee_config -!wee_database -!wee_debug -!wee_device -!wee_extension -!wee_import -!wee_reports -!weewx.install !weewx.service -!weewxd -!wunderfixer -!weewx-version.patch -!genplot.py +!weewx.sysusers +!weewx.tmpfiles @@ -4,72 +4,50 @@ # Supports automatic update checking pkgname=weewx -_MAJOR=4 -_MINOR=10 -_PATCH=2 +_MAJOR=5 +_MINOR=0 +_PATCH=0 pkgver=$_MAJOR.$_MINOR.$_PATCH function _dl_url { echo "https://github.com/weewx/weewx/archive/refs/tags/v$1.$2.$3.tar.gz" } -pkgrel=7 +pkgrel=1 pkgdesc="Software for logging data from weather stations" arch=("any") url="http://www.weewx.com/" -license=("GPL3") +license=("GPL-3.0-or-later") depends=("python" - "python-daemon" - "python-six" + "python-cheetah3" "python-configobj" - "python-pyserial" - "python-pillow" - "python-pyusb" - "python-cheetah3") -optdepends=("python-pyephem: extended almanac information" - "mariadb-clients: MariaDB support" - "python-mysqlclient: MariaDB support") + "python-pillow") +optdepends=("python-pyserial: serial port support" + "python-pyusb: USB port support" + "python-pyephem: extended celestial information" + "python-pymysql: MySQL or MariaDB support") +makedepends=("mkdocs" + "mkdocs-material" + "mkdocs-material-extensions") backup=("etc/weewx/weewx.conf") source=("$pkgname-$pkgver.tar.xz::$(_dl_url $_MAJOR $_MINOR $_PATCH)" - "wee_config" - "wee_database" - "wee_debug" - "wee_device" - "wee_extension" - "wee_import" - "wee_reports" - "weewxd" - "wunderfixer" - "weewx.service" - "genplot.py" - "weewx-version.patch" - "pillow-rect.patch") -sha512sums=('8fca9cd7720a29687a0d900e4d89ec2ce5ca5d2aa36bc5b5909ea14ecb849cdbdb6e699cf1c3a0d5505c89ad8c309517db32fd8dc4a0ae4704dfd5ed0cc5747f' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP') + "weewx.sysusers" + "weewx.tmpfiles" + "weewx.service") +sha512sums=('c3eb23048012f2bab7eac0a25f6dfad4da4ff1591601f7242cf7fec91343e88f3014b7281c021c75cfdbb5b4e73285ab8605325a3c7771e90a5016e3d574dc3b' + '6015b870143f6b8ae094b3f94ad53323be8a083f11c177dc508315fb3bbc20dd318124e6ccd41ba9d0388828e18c4b4ae6ce7c4a35ac0cab442eca9e8bbbca2d' + '9875bf209439f62fc2e6773b1283a6ed0a2adbe33e7b6461678a5f036679570a98393814eeadcb20b9d9160b79aca0b1a1769eab39be2d1913b64439abd76f62' + '4744fec4faf63b36f9c82a7404e4ecc749eb07e8d90640465ff7a2ae20cdb2560348b0a125467fad215d0e51d88d27a991dc0196899e53d19479dec942d6e52d') _watch="http://www.weewx.com/downloads/" -prepare() { - cd "$srcdir/${pkgname}-${pkgver}" - patch --strip=1 --input="$srcdir/weewx-version.patch" - patch --strip=1 --input="$srcdir/pillow-rect.patch" - cp -v "$srcdir/genplot.py" bin/weeplot -} - build() { cd "$srcdir/${pkgname}-${pkgver}" - python setup.py build + + echo "Compiling Python bytecode" + python -m compileall -q "src" + + echo "Building documentation" + make --quiet build-docs } _install() { @@ -88,79 +66,78 @@ _install() { package() { cd "$srcdir/${pkgname}-${pkgver}" - echo "Renning install using setup.py script" - local setup_base="$pkgdir/${pkgname}" - python setup.py install --root="$setup_base" --optimize=1 --skip-build --no-prompt - - local target_bin_dir="$pkgdir/usr/bin" - local target_doc_dir="$pkgdir/usr/share/doc/$pkgname" - local target_etc_dir="$pkgdir/etc/$pkgname" - local target_lib_dir="$pkgdir/usr/lib/$pkgname" - local target_share_dir="$pkgdir/usr/share/$pkgname" - - local target_license_file="$pkgdir/usr/share/licenses/$pkgname/LICENSE" - local target_unit="${pkgname}.service" - local target_unit_file="$pkgdir/usr/lib/systemd/system/${target_unit}" - local target_conf_file="$target_etc_dir/weewx.conf" - - local source_bin=("${srcdir}/wee_config" - "${srcdir}/wee_database" - "${srcdir}/wee_debug" - "${srcdir}/wee_device" - "${srcdir}/wee_extension" - "${srcdir}/wee_import" - "${srcdir}/wee_reports" - "${srcdir}/weewxd" - "${srcdir}/wunderfixer") - local source_unit_file=("${srcdir}/${target_unit}") - local source_doc=("${setup_base}/home/weewx/docs"/*) - local source_conf_file="${setup_base}/home/weewx/weewx.conf" - local source_etc=("${setup_base}/home/weewx/skins" "$source_conf_file") - local source_lib=("${setup_base}/home/weewx/bin"/*) - local source_license_file=("${setup_base}/home/weewx/LICENSE.txt") - local source_share=("${setup_base}/home/weewx/examples" - "${setup_base}/home/weewx/util/apache" - "${setup_base}/home/weewx/util/import" - "${setup_base}/home/weewx/util/logrotate.d" - "${setup_base}/home/weewx/util/logwatch" - "${setup_base}/home/weewx/util/newsyslog.d" - "${setup_base}/home/weewx/util/rsyslog.d" - "${setup_base}/home/weewx/util/udev") - - echo "Installing binaries" - _install "$target_bin_dir" 755 "${source_bin[@]}" - - echo "Installing library files" - _install "$target_lib_dir" 644 "${source_lib[@]}" - - echo "Installing configuration" - _install "$target_etc_dir" 644 "${source_etc[@]}" - - echo "Installing documentation" - _install "$target_doc_dir" 644 "${source_doc[@]}" - - echo "Installing shared files" - _install "$target_share_dir" 644 "${source_share[@]}" - - echo "Installing license" - install -Dm644 "$source_license_file" "$target_license_file" - - echo "Installing unit file" - install -Dm644 "$source_unit_file" "$target_unit_file" - - echo "Removing temp setup" - rm -r "$setup_base" - - echo "Removing unnecessary files" - find "$pkgdir" -name "*.egg-info" -type f -delete - - echo "Fixing ownership" - chown -R root:root "$pkgdir" - - echo "Adapting configuration file" - sed -i "$target_conf_file" \ - -r -e "s@(.*WEEWX_ROOT).*@\1 = /@g" \ - -r -e "s@(.*SKIN_ROOT).*@\1 = /etc/$pkgname/skins@g" \ - -r -e "s@(.*HTML_ROOT).*@\1 = /srv/http/html/$pkgname@g" \ - -r -e "s@(.*SQLITE_ROOT).*@\1 = /var/lib/$pkgname@g" + local PYTHON='python' + local weewx_bindir='/usr/lib/weewx' + local weewx_sharedir="/usr/share/weewx" + local weewx_etcdir="/etc/weewx" + local weewx_vardir="/var/lib/weewx" + local entrypoints=('weewxd' 'weectl') + + local bindir="$pkgdir/usr/bin" + local libdir="${pkgdir}${weewx_bindir}" + local sharedir="${pkgdir}${weewx_sharedir}" + local licensedir="$pkgdir/usr/share/licenses/weewx" + local docdir="$pkgdir/usr/share/doc/weewx" + local etcdir="${pkgdir}${weewx_etcdir}" + local unitdir="$pkgdir/usr/lib/systemd/system" + local sysusersdir="$pkgdir/usr/lib/sysusers.d" + local tmpfilesdir="$pkgdir/usr/lib/tmpfiles.d" + local udevdir="$pkgdir/usr/lib/udev/rules.d" + + echo "Copying source files" + [[ -d "$libdir" ]] || mkdir -p "$libdir" + _install "$libdir" 644 "src"/* + _install "$libdir" 755 "src/weewx_data/bin" + + echo "Creating entrypoints" + [[ -d "$bindir" ]] || mkdir -p "$bindir" + for f in ${entrypoints[@]}; do + echo "Creating entrypoint $f" + sed \ + -e "s%WEEWX_BINDIR=.*%WEEWX_BINDIR=\"${weewx_bindir}\"%" \ + -e "s%WEEWX_PYTHON=.*%WEEWX_PYTHON=\"${PYTHON}\"%" \ + "bin/$f" > "$bindir/$f" + chmod 755 "$bindir/$f" + done + + echo "Copying license and copyright" + install -Dm644 "docs_src/copyright.md" "$licensedir/copyright.md" + install -Dm644 "LICENSE.txt" "$licensedir/LICENSE.txt" + + echo "Copying documentation" + [[ -d "$docdir" ]] || mkdir -p "$docdir" + _install "$docdir" 644 "build/docs"/* + + echo "Copying skins" + [[ -d "$sharedir" ]] || mkdir -p "$sharedir" + _install "$sharedir" 644 "src/weewx_data/skins" + + echo "Copying ancillary files" + _install "$sharedir" 644 "src/weewx_data/examples" + _install "$sharedir" 644 "src/weewx_data/util/import" + _install "$sharedir" 644 "src/weewx_data/util/logwatch" + _install "$sharedir" 644 "src/weewx_data/util/systemd" + _install "$sharedir" 644 "src/weewx_data/util/udev" + + echo "Creating configuration file" + [[ -d "$etcdir" ]] || mkdir -p "$etcdir" + sed \ + -e "/log_failure =.*/aWEEWX_ROOT = $weewx_bindir" \ + -e "s%SKIN_ROOT =.*%SKIN_ROOT = $weewx_sharedir/skins%" \ + -e "s%HTML_ROOT = public_html%HTML_ROOT = $weewx_vardir/www%" \ + -e "s%SQLITE_ROOT = .*%SQLITE_ROOT = $weewx_vardir%" \ + "src/weewx_data/weewx.conf" > "$etcdir/weewx.conf" + chmod 640 "$etcdir/weewx.conf" + + echo "Creating systemd unit" + install -Dm640 "$srcdir/weewx.service" "$unitdir/weewx.service" + + echo "Creating system user definition" + install -Dm640 "$srcdir/weewx.sysusers" "$sysusersdir/weewx.conf" + + echo "Creating tmpfiles definition" + install -Dm640 "$srcdir/weewx.tmpfiles" "$tmpfilesdir/weewx.conf" + + echo "Creating udev ruleset" + install -Dm640 "src/weewx_data/util/udev/rules.d/weewx.rules" "$udevdir/weewx.rules" } diff --git a/genplot.py b/genplot.py deleted file mode 100644 index 7094d770e052..000000000000 --- a/genplot.py +++ /dev/null @@ -1,737 +0,0 @@ -# -# Copyright (c) 2009-2023 Tom Keffer <tkeffer@gmail.com> -# -# See the file LICENSE.txt for your full rights. -# -"""Routines for generating image plots.""" - -import colorsys -import locale -import os -import time - -from PIL import Image, ImageDraw, ImageFont - -import weeplot.utilities -import weeutil.weeutil -from weeplot.utilities import tobgr -from weeutil.weeutil import max_with_none, min_with_none, to_bool - -# Test if this version of Pillow has ImageFont.getbbox. If not, we will activate a workaround. -try: - ImageFont.ImageFont.getbbox -except AttributeError: - PIL_HAS_BBOX = False -else: - PIL_HAS_BBOX = True - - -class GeneralPlot(object): - """Holds various parameters necessary for a plot. It should be specialized by the type of plot. - """ - def __init__(self, plot_dict): - """Initialize an instance of GeneralPlot. - - plot_dict: an instance of ConfigObj, or something that looks like it. - """ - - self.line_list = [] - - self.xscale = (None, None, None) - self.yscale = (None, None, None) - - self.anti_alias = int(plot_dict.get('anti_alias', 1)) - - self.image_width = int(plot_dict.get('image_width', 300)) * self.anti_alias - self.image_height = int(plot_dict.get('image_height', 180)) * self.anti_alias - self.image_background_color = tobgr(plot_dict.get('image_background_color', '0xf5f5f5')) - - self.chart_background_color = tobgr(plot_dict.get('chart_background_color', '0xd8d8d8')) - self.chart_gridline_color = tobgr(plot_dict.get('chart_gridline_color', '0xa0a0a0')) - color_list = plot_dict.get('chart_line_colors', ['0xff0000', '0x00ff00', '0x0000ff']) - fill_color_list = plot_dict.get('chart_fill_colors', color_list) - width_list = plot_dict.get('chart_line_width', [1, 1, 1]) - self.chart_line_colors = [tobgr(v) for v in color_list] - self.chart_fill_colors = [tobgr(v) for v in fill_color_list] - self.chart_line_widths = [int(v) for v in width_list] - - - self.top_label_font_path = plot_dict.get('top_label_font_path') - self.top_label_font_size = int(plot_dict.get('top_label_font_size', 10)) * self.anti_alias - - self.unit_label = None - self.unit_label_font_path = plot_dict.get('unit_label_font_path') - self.unit_label_font_color = tobgr(plot_dict.get('unit_label_font_color', '0x000000')) - self.unit_label_font_size = int(plot_dict.get('unit_label_font_size', 10)) * self.anti_alias - self.unit_label_position = (10 * self.anti_alias, 0) - - self.bottom_label = u"" - self.bottom_label_font_path = plot_dict.get('bottom_label_font_path') - self.bottom_label_font_color= tobgr(plot_dict.get('bottom_label_font_color', '0x000000')) - self.bottom_label_font_size = int(plot_dict.get('bottom_label_font_size', 10)) * self.anti_alias - self.bottom_label_offset = int(plot_dict.get('bottom_label_offset', 3)) - - self.axis_label_font_path = plot_dict.get('axis_label_font_path') - self.axis_label_font_color = tobgr(plot_dict.get('axis_label_font_color', '0x000000')) - self.axis_label_font_size = int(plot_dict.get('axis_label_font_size', 10)) * self.anti_alias - - # Make sure the formats used for the x- and y-axes are in unicode. - self.x_label_format = plot_dict.get('x_label_format') - self.y_label_format = plot_dict.get('y_label_format') - - self.x_nticks = int(plot_dict.get('x_nticks', 10)) - self.y_nticks = int(plot_dict.get('y_nticks', 10)) - - self.x_label_spacing = int(plot_dict.get('x_label_spacing', 2)) - self.y_label_spacing = int(plot_dict.get('y_label_spacing', 2)) - - # Calculate sensible margins for the given image and font sizes. - self.y_label_side = plot_dict.get('y_label_side', 'left') - if self.y_label_side == 'left' or self.y_label_side == 'both': - self.lmargin = int(4.0 * self.axis_label_font_size) - else: - self.lmargin = 20 * self.anti_alias - if self.y_label_side == 'right' or self.y_label_side == 'both': - self.rmargin = int(4.0 * self.axis_label_font_size) - else: - self.rmargin = 20 * self.anti_alias - self.bmargin = int(1.5 * (self.bottom_label_font_size + self.axis_label_font_size) + 0.5) - self.tmargin = int(1.5 * self.top_label_font_size + 0.5) - self.tbandht = int(1.2 * self.top_label_font_size + 0.5) - self.padding = 3 * self.anti_alias - - self.render_rose = False - self.rose_width = int(plot_dict.get('rose_width', 21)) - self.rose_height = int(plot_dict.get('rose_height', 21)) - self.rose_diameter = int(plot_dict.get('rose_diameter', 10)) - self.rose_position = (self.lmargin + self.padding + 5, self.image_height - self.bmargin - self.padding - self.rose_height) - self.rose_rotation = None - self.rose_label = plot_dict.get('rose_label', 'N') - self.rose_label_font_path = plot_dict.get('rose_label_font_path', self.bottom_label_font_path) - self.rose_label_font_size = int(plot_dict.get('rose_label_font_size', 10)) - self.rose_label_font_color = tobgr(plot_dict.get('rose_label_font_color', '0x000000')) - self.rose_line_width = int(plot_dict.get('rose_line_width', 1)) - self.rose_color = plot_dict.get('rose_color') - if self.rose_color is not None: - self.rose_color = tobgr(self.rose_color) - - # Show day/night transitions - self.show_daynight = to_bool(plot_dict.get('show_daynight', False)) - self.daynight_day_color = tobgr(plot_dict.get('daynight_day_color', '0xffffff')) - self.daynight_night_color = tobgr(plot_dict.get('daynight_night_color', '0xf0f0f0')) - self.daynight_edge_color = tobgr(plot_dict.get('daynight_edge_color', '0xefefef')) - self.daynight_gradient = int(plot_dict.get('daynight_gradient', 20)) - - # initialize the location - self.latitude = None - self.longitude = None - - # normalize the font paths relative to the skin directory - skin_dir = plot_dict.get('skin_dir', '') - self.top_label_font_path = self.normalize_path(skin_dir, self.top_label_font_path) - self.bottom_label_font_path = self.normalize_path(skin_dir, self.bottom_label_font_path) - self.unit_label_font_path = self.normalize_path(skin_dir, self.unit_label_font_path) - self.axis_label_font_path = self.normalize_path(skin_dir, self.axis_label_font_path) - self.rose_label_font_path = self.normalize_path(skin_dir, self.rose_label_font_path) - - @staticmethod - def normalize_path(skin_dir, path): - if path is None: - return None - return os.path.join(skin_dir, path) - - def setBottomLabel(self, bottom_label): - """Set the label to be put at the bottom of the plot. """ - self.bottom_label = bottom_label - - def setUnitLabel(self, unit_label): - """Set the label to be used to show the units of the plot. """ - self.unit_label = unit_label - - def setXScaling(self, xscale): - """Set the X scaling. - - xscale: A 3-way tuple (xmin, xmax, xinc) - """ - self.xscale = xscale - - def setYScaling(self, yscale): - """Set the Y scaling. - - yscale: A 3-way tuple (ymin, ymax, yinc) - """ - self.yscale = yscale - - def addLine(self, line): - """Add a line to be plotted. - - line: an instance of PlotLine - """ - if None in line.x: - raise weeplot.ViolatedPrecondition("X vector cannot have any values 'None' ") - self.line_list.append(line) - - def setLocation(self, lat, lon): - self.latitude = lat - self.longitude = lon - - def setDayNight(self, showdaynight, daycolor, nightcolor, edgecolor): - """Configure day/night bands. - - showdaynight: Boolean flag indicating whether to draw day/night bands - - daycolor: color for day bands - - nightcolor: color for night bands - - edgecolor: color for transition between day and night - """ - self.show_daynight = showdaynight - self.daynight_day_color = daycolor - self.daynight_night_color = nightcolor - self.daynight_edge_color = edgecolor - - def render(self): - """Traverses the universe of things that have to be plotted in this image, rendering - them and returning the results as a new Image object. - """ - - # NB: In what follows the variable 'draw' is an instance of an ImageDraw object and is in pixel units. - # The variable 'sdraw' is an instance of ScaledDraw and its units are in the "scaled" units of the plot - # (e.g., the horizontal scaling might be for seconds, the vertical for degrees Fahrenheit.) - image = Image.new("RGB", (self.image_width, self.image_height), self.image_background_color) - draw = ImageDraw.ImageDraw(image) - draw.rectangle(((self.lmargin,self.tmargin), - (self.image_width - self.rmargin, self.image_height - self.bmargin)), - fill=self.chart_background_color) - - self._renderBottom(draw) - self._renderTopBand(draw) - - self._calcXScaling() - self._calcYScaling() - self._calcXLabelFormat() - self._calcYLabelFormat() - - sdraw = self._getScaledDraw(draw) - if self.show_daynight: - self._renderDayNight(sdraw) - self._renderXAxes(sdraw) - self._renderYAxes(sdraw) - self._renderPlotLines(sdraw) - if self.render_rose: - self._renderRose(image, draw) - - if self.anti_alias != 1: - image.thumbnail((self.image_width / self.anti_alias, - self.image_height / self.anti_alias), - Image.LANCZOS) - - return image - - def _getScaledDraw(self, draw): - """Returns an instance of ScaledDraw, with the appropriate scaling. - - draw: An instance of ImageDraw - """ - sdraw = weeplot.utilities.ScaledDraw( - draw, - ( - (self.lmargin + self.padding, self.tmargin + self.padding), - (self.image_width - self.rmargin - self.padding, self.image_height - self.bmargin - self.padding) - ), - ( - (self.xscale[0], self.yscale[0]), - (self.xscale[1], self.yscale[1]) - ) - ) - return sdraw - - def _renderDayNight(self, sdraw): - """Draw vertical bands for day/night.""" - (first, transitions) = weeutil.weeutil.getDayNightTransitions( - self.xscale[0], self.xscale[1], self.latitude, self.longitude) - color = self.daynight_day_color \ - if first == 'day' else self.daynight_night_color - xleft = self.xscale[0] - for x in transitions: - sdraw.rectangle(((xleft,self.yscale[0]), - (x,self.yscale[1])), fill=color) - xleft = x - color = self.daynight_night_color \ - if color == self.daynight_day_color else self.daynight_day_color - sdraw.rectangle(((xleft,self.yscale[0]), - (self.xscale[1],self.yscale[1])), fill=color) - if self.daynight_gradient: - if first == 'day': - color1 = self.daynight_day_color - color2 = self.daynight_night_color - else: - color1 = self.daynight_night_color - color2 = self.daynight_day_color - nfade = self.daynight_gradient - # gradient is longer at the poles than the equator - d = 120 + 300 * (1 - (90.0 - abs(self.latitude)) / 90.0) - for i in range(len(transitions)): - last_ = self.xscale[0] if i == 0 else transitions[i-1] - next_ = transitions[i+1] if i < len(transitions)-1 else self.xscale[1] - for z in range(1,nfade): - c = blend_hls(color2, color1, float(z)/float(nfade)) - rgbc = int2rgbstr(c) - x1 = transitions[i]-d*(nfade+1)/2+d*z - if last_ < x1 < next_: - sdraw.rectangle(((x1, self.yscale[0]), - (x1+d, self.yscale[1])), - fill=rgbc) - if color1 == self.daynight_day_color: - color1 = self.daynight_night_color - color2 = self.daynight_day_color - else: - color1 = self.daynight_day_color - color2 = self.daynight_night_color - # draw a line at the actual sunrise/sunset - for x in transitions: - sdraw.line((x,x),(self.yscale[0],self.yscale[1]), - fill=self.daynight_edge_color) - - def _renderXAxes(self, sdraw): - """Draws the x axis and vertical constant-x lines, as well as the labels. """ - - axis_label_font = weeplot.utilities.get_font_handle(self.axis_label_font_path, - self.axis_label_font_size) - - drawlabelcount = 0 - for x in weeutil.weeutil.stampgen(self.xscale[0], self.xscale[1], self.xscale[2]) : - sdraw.line((x, x), - (self.yscale[0], self.yscale[1]), - fill=self.chart_gridline_color, - width=self.anti_alias) - if drawlabelcount % self.x_label_spacing == 0 : - xlabel = self._genXLabel(x) - if PIL_HAS_BBOX: - axis_label_width = sdraw.draw.textlength(xlabel, font=axis_label_font) - else: - axis_label_width, _ = sdraw.draw.textsize(xlabel, font=axis_label_font) - xpos = sdraw.xtranslate(x) - sdraw.draw.text((xpos - axis_label_width/2, self.image_height - self.bmargin + 2), - xlabel, fill=self.axis_label_font_color, font=axis_label_font) - drawlabelcount += 1 - - def _renderYAxes(self, sdraw): - """Draws the y axis and horizontal constant-y lines, as well as the labels. - Should be sufficient for most purposes. - """ - nygridlines = int((self.yscale[1] - self.yscale[0]) / self.yscale[2] + 1.5) - axis_label_font = weeplot.utilities.get_font_handle(self.axis_label_font_path, - self.axis_label_font_size) - - # Draw the (constant y) grid lines - for i in range(nygridlines) : - y = self.yscale[0] + i * self.yscale[2] - sdraw.line((self.xscale[0], self.xscale[1]), (y, y), fill=self.chart_gridline_color, - width=self.anti_alias) - # Draw a label on every other line: - if i % self.y_label_spacing == 0 : - ylabel = self._genYLabel(y) - if PIL_HAS_BBOX: - left, top, right, bottom = axis_label_font.getbbox(ylabel) - axis_label_width, axis_label_height = right - left, bottom - top - else: - axis_label_width, axis_label_height = sdraw.draw.textsize(ylabel, - font=axis_label_font) - ypos = sdraw.ytranslate(y) - # We want to treat Truetype and bitmapped fonts the same. By default, Truetype - # measures the top of the bounding box at the top of the ascender, while it's - # the top of the text for bitmapped. Specify an anchor of "lt" (left, top) for - # both. NB: argument "anchor" has been around at least as early as - # Pillow V5.0 (2018), but was not implemented until V8.0.0. - if self.y_label_side == 'left' or self.y_label_side == 'both': - sdraw.draw.text((self.lmargin - axis_label_width - 2, ypos - axis_label_height/2), - ylabel, fill=self.axis_label_font_color, font=axis_label_font, - anchor="lt") - if self.y_label_side == 'right' or self.y_label_side == 'both': - sdraw.draw.text((self.image_width - self.rmargin + 4, ypos - axis_label_height/2), - ylabel, fill=self.axis_label_font_color, font=axis_label_font, - anchor="lt") - - def _renderPlotLines(self, sdraw): - """Draw the collection of lines, using a different color for each one. Because there is - a limited set of colors, they need to be recycled if there are very many lines. - """ - nlines = len(self.line_list) - ncolors = len(self.chart_line_colors) - nfcolors = len(self.chart_fill_colors) - nwidths = len(self.chart_line_widths) - - # Draw them in reverse order, so the first line comes out on top of the image - for j, this_line in enumerate(self.line_list[::-1]): - - iline=nlines-j-1 - color = self.chart_line_colors[iline%ncolors] if this_line.color is None else this_line.color - fill_color = self.chart_fill_colors[iline%nfcolors] if this_line.fill_color is None else this_line.fill_color - width = (self.chart_line_widths[iline%nwidths] if this_line.width is None else this_line.width) * self.anti_alias - - # Calculate the size of a gap in data - maxdx = None - if this_line.line_gap_fraction is not None: - maxdx = this_line.line_gap_fraction * (self.xscale[1] - self.xscale[0]) - - if this_line.plot_type == 'line': - ms = this_line.marker_size - if ms is not None: - ms *= self.anti_alias - sdraw.line(this_line.x, - this_line.y, - line_type=this_line.line_type, - marker_type=this_line.marker_type, - marker_size=ms, - fill = color, - width = width, - maxdx = maxdx) - elif this_line.plot_type == 'bar' : - for x, y, bar_width in zip(this_line.x, this_line.y, this_line.bar_width): - if y is None: - continue - sdraw.rectangle(((x - bar_width, self.yscale[0]), (x, y)), fill=fill_color, outline=color) - elif this_line.plot_type == 'vector' : - for (x, vec) in zip(this_line.x, this_line.y): - sdraw.vector(x, vec, - vector_rotate = this_line.vector_rotate, - fill = color, - width = width) - self.render_rose = True - self.rose_rotation = this_line.vector_rotate - if self.rose_color is None: - self.rose_color = color - - def _renderBottom(self, draw): - """Draw anything at the bottom (just some text right now). """ - bottom_label_font = weeplot.utilities.get_font_handle(self.bottom_label_font_path, - self.bottom_label_font_size) - if PIL_HAS_BBOX: - left, top, right, bottom = bottom_label_font.getbbox(self.bottom_label) - bottom_label_width, bottom_label_height = right - left, bottom - top - else: - bottom_label_width, bottom_label_height = draw.textsize(self.bottom_label, - font=bottom_label_font) - draw.text(((self.image_width - bottom_label_width)/2, - self.image_height - bottom_label_height - self.bottom_label_offset), - self.bottom_label, - fill=self.bottom_label_font_color, - font=bottom_label_font, - anchor="lt") - - def _renderTopBand(self, draw): - """Draw the top band and any text in it. """ - # Draw the top band rectangle - draw.rectangle(((0,0), - (self.image_width, self.tbandht)), - fill = self.chart_background_color) - - # Put the units in the upper left corner - unit_label_font = weeplot.utilities.get_font_handle(self.unit_label_font_path, - self.unit_label_font_size) - if self.unit_label: - if self.y_label_side == 'left' or self.y_label_side == 'both': - draw.text(self.unit_label_position, - self.unit_label, - fill=self.unit_label_font_color, - font=unit_label_font) - if self.y_label_side == 'right' or self.y_label_side == 'both': - unit_label_position_right = (self.image_width - self.rmargin + 4, 0) - draw.text(unit_label_position_right, - self.unit_label, - fill=self.unit_label_font_color, - font=unit_label_font) - - top_label_font = weeplot.utilities.get_font_handle(self.top_label_font_path, - self.top_label_font_size) - - # The top label is the appended label_list. However, it has to be drawn in segments - # because each label may be in a different color. For now, append them together to get - # the total width - top_label = u' '.join([line.label for line in self.line_list]) - if PIL_HAS_BBOX: - top_label_width= draw.textlength(top_label, font=top_label_font) - else: - top_label_width, _ = draw.textsize(top_label, font=top_label_font) - - x = (self.image_width - top_label_width)/2 - y = 0 - - ncolors = len(self.chart_line_colors) - for i, this_line in enumerate(self.line_list): - color = self.chart_line_colors[i%ncolors] if this_line.color is None else this_line.color - # Draw a label - draw.text( (x,y), this_line.label, fill = color, font = top_label_font) - # Now advance the width of the label we just drew, plus a space: - if PIL_HAS_BBOX: - label_width = draw.textlength(this_line.label + u' ', font= top_label_font) - else: - label_width, _ = draw.textsize(this_line.label + u' ', font= top_label_font) - x += label_width - - def _renderRose(self, image, draw): - """Draw a compass rose.""" - - rose_center_x = self.rose_width/2 + 1 - rose_center_y = self.rose_height/2 + 1 - barb_width = 3 - barb_height = 3 - # The background is all white with a zero alpha (totally transparent) - rose_image = Image.new("RGBA", (self.rose_width, self.rose_height), (0x00, 0x00, 0x00, 0x00)) - rose_draw = ImageDraw.Draw(rose_image) - - fill_color = add_alpha(self.rose_color) - # Draw the arrow straight up (North). First the shaft: - rose_draw.line( ((rose_center_x, 0), (rose_center_x, self.rose_height)), - width = self.rose_line_width, - fill = fill_color) - # Now the left barb: - rose_draw.line( ((rose_center_x - barb_width, barb_height), (rose_center_x, 0)), - width = self.rose_line_width, - fill = fill_color) - # And the right barb: - rose_draw.line( ((rose_center_x, 0), (rose_center_x + barb_width, barb_height)), - width = self.rose_line_width, - fill = fill_color) - - rose_draw.ellipse(((rose_center_x - self.rose_diameter/2, - rose_center_y - self.rose_diameter/2), - (rose_center_x + self.rose_diameter/2, - rose_center_y + self.rose_diameter/2)), - outline = fill_color) - - # Rotate if necessary: - if self.rose_rotation: - rose_image = rose_image.rotate(self.rose_rotation) - rose_draw = ImageDraw.Draw(rose_image) - - # Calculate the position of the "N" label: - rose_label_font = weeplot.utilities.get_font_handle(self.rose_label_font_path, - self.rose_label_font_size) - if PIL_HAS_BBOX: - left, top, right, bottom = rose_label_font.getbbox(self.rose_label) - rose_label_width, rose_label_height = right - left, bottom - top - else: - rose_label_width, rose_label_height = draw.textsize(self.rose_label, - font=rose_label_font) - - # Draw the label in the middle of the (possibly) rotated arrow - rose_draw.text((rose_center_x - rose_label_width/2 - 1, - rose_center_y - rose_label_height/2 - 1), - self.rose_label, - fill=add_alpha(self.rose_label_font_color), - font=rose_label_font, - anchor="lt") - - # Paste the image of the arrow on to the main plot. The alpha - # channel of the image will be used as the mask. - # This will cause the arrow to overlay the background plot - image.paste(rose_image, self.rose_position, rose_image) - - def _calcXScaling(self): - """Calculates the x scaling. It will probably be specialized by - plots where the x-axis represents time. - """ - (xmin, xmax) = self._calcXMinMax() - - self.xscale = weeplot.utilities.scale(xmin, xmax, self.xscale, nsteps=self.x_nticks) - - def _calcYScaling(self): - """Calculates y scaling. Can be used 'as-is' for most purposes.""" - # The filter is necessary because unfortunately the value 'None' is not - # excluded from min and max (i.e., min(None, x) is not necessarily x). - # The try block is necessary because min of an empty list throws a - # ValueError exception. - ymin = ymax = None - for line in self.line_list: - if line.plot_type == 'vector': - try: - # For progressive vector plots, we want the magnitude of the complex vector - yline_max = max(abs(c) for c in [v for v in line.y if v is not None]) - except ValueError: - yline_max = None - yline_min = - yline_max if yline_max is not None else None - else: - yline_min = min_with_none(line.y) - yline_max = max_with_none(line.y) - ymin = min_with_none([ymin, yline_min]) - ymax = max_with_none([ymax, yline_max]) - - if ymin is None and ymax is None : - # No valid data. Pick an arbitrary scaling - self.yscale=(0.0, 1.0, 0.2) - else: - self.yscale = weeplot.utilities.scale(ymin, ymax, self.yscale, nsteps=self.y_nticks) - - def _calcXLabelFormat(self): - if self.x_label_format is None: - self.x_label_format = weeplot.utilities.pickLabelFormat(self.xscale[2]) - - def _calcYLabelFormat(self): - if self.y_label_format is None: - self.y_label_format = weeplot.utilities.pickLabelFormat(self.yscale[2]) - - def _genXLabel(self, x): - xlabel = locale.format_string(self.x_label_format, x) - return xlabel - - def _genYLabel(self, y): - ylabel = locale.format_string(self.y_label_format, y) - return ylabel - - def _calcXMinMax(self): - xmin = xmax = None - for line in self.line_list: - xline_min = min_with_none(line.x) - xline_max = max_with_none(line.x) - # If the line represents a bar chart, then the actual minimum has to - # be adjusted for the bar width of the first point - if line.plot_type == 'bar': - xline_min = xline_min - line.bar_width[0] - xmin = min_with_none([xmin, xline_min]) - xmax = max_with_none([xmax, xline_max]) - return xmin, xmax - - -class TimePlot(GeneralPlot) : - """Class that specializes GeneralPlot for plots where the x-axis is time.""" - - def _calcXScaling(self): - """Specialized version for time plots.""" - if None in self.xscale: - (xmin, xmax) = self._calcXMinMax() - self.xscale = weeplot.utilities.scaletime(xmin, xmax) - - def _calcXLabelFormat(self): - """Specialized version for time plots. Assumes that time is in unix epoch time.""" - if self.x_label_format is None: - (xmin, xmax) = self._calcXMinMax() - if xmin is not None and xmax is not None: - delta = xmax - xmin - if delta > 30*24*3600: - self.x_label_format = u"%x" - elif delta > 24*3600: - self.x_label_format = u"%x %X" - else: - self.x_label_format = u"%X" - - def _genXLabel(self, x): - """Specialized version for time plots. Assumes that time is in unix epoch time.""" - if self.x_label_format is None: - return u'' - time_tuple = time.localtime(x) - # There are still some strftimes out there that don't support Unicode. - try: - xlabel = time.strftime(self.x_label_format, time_tuple) - except UnicodeEncodeError: - # Convert it to UTF8, then back again: - xlabel = time.strftime(self.x_label_format.encode('utf-8'), time_tuple).decode('utf-8') - return xlabel - - -class PlotLine(object): - """Represents a single line (or bar) in a plot. """ - def __init__(self, x, y, label='', color=None, fill_color=None, width=None, plot_type='line', - line_type='solid', marker_type=None, marker_size=10, - bar_width=None, vector_rotate = None, line_gap_fraction=None): - self.x = x - self.y = y - self.label = label - self.plot_type = plot_type - self.line_type = line_type - self.marker_type = marker_type - self.marker_size = marker_size - self.color = color - self.fill_color = fill_color - self.width = width - self.bar_width = bar_width - self.vector_rotate = vector_rotate - self.line_gap_fraction = line_gap_fraction - - -def blend_hls(c, bg, alpha): - """Fade from c to bg using alpha channel where 1 is solid and 0 is - transparent. This fades across the hue, saturation, and lightness.""" - return blend(c, bg, alpha, alpha, alpha) - - -def blend_ls(c, bg, alpha): - """Fade from c to bg where 1 is solid and 0 is transparent. - Change only the lightness and saturation, not hue.""" - return blend(c, bg, 1.0, alpha, alpha) - - -def blend(c, bg, alpha_h, alpha_l, alpha_s): - """Fade from c to bg in the hue, lightness, saturation colorspace. - Added hue directionality to choose shortest circular hue path e.g. - https://stackoverflow.com/questions/1416560/hsl-interpolation - Also, grey detection to minimize colour wheel travel. Interesting resource: - http://davidjohnstone.net/pages/lch-lab-colour-gradient-picker - """ - - r1,g1,b1 = int2rgb(c) - h1,l1,s1 = colorsys.rgb_to_hls(r1/255.0, g1/255.0, b1/255.0) - - r2,g2,b2 = int2rgb(bg) - h2,l2,s2 = colorsys.rgb_to_hls(r2/255.0, g2/255.0, b2/255.0) - - # Check if either of the values is grey (saturation 0), - # in which case don't needlessly reset hue to '0', reducing travel around colour wheel - if s1 == 0: h1 = h2 - if s2 == 0: h2 = h1 - - h_delta = h2 - h1 - - if abs(h_delta) > 0.5: - # If interpolating over more than half-circle (0.5 radians) take shorter, opposite direction... - h_range = 1.0 - abs(h_delta) - h_dir = +1.0 if h_delta < 0.0 else -1.0 - - # Calculte h based on line back from h2 as proportion of h_range and alpha - h = h2 - ( h_dir * h_range * alpha_h ) - - # Clamp h within 0.0 to 1.0 range - h = h + 1.0 if h < 0.0 else h - h = h - 1.0 if h > 1.0 else h - else: - # Interpolating over less than a half-circle, so use normal interpolation as before - h = alpha_h * h1 + (1 - alpha_h) * h2 - - l = alpha_l * l1 + (1 - alpha_l) * l2 - s = alpha_s * s1 + (1 - alpha_s) * s2 - - r,g,b = colorsys.hls_to_rgb(h, l, s) - - r = round(r * 255.0) - g = round(g * 255.0) - b = round(b * 255.0) - - t = rgb2int(int(r),int(g),int(b)) - - return int(t) - - -def int2rgb(x): - b = (x >> 16) & 0xff - g = (x >> 8) & 0xff - r = x & 0xff - return r,g,b - - -def int2rgbstr(x): - return '#%02x%02x%02x' % int2rgb(x) - - -def rgb2int(r,g,b): - return r + g*256 + b*256*256 - - -def add_alpha(i): - """Add an opaque alpha channel to an integer RGB value""" - r = i & 0xff - g = (i >> 8) & 0xff - b = (i >> 16) & 0xff - a = 0xff # Opaque alpha - return r,g,b,a diff --git a/pillow-rect.patch b/pillow-rect.patch deleted file mode 100644 index 5d2aa04ec641..000000000000 --- a/pillow-rect.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/bin/weeplot/utilities.py b/bin/weeplot/utilities.py -index 73e955bd..f1c9d33a 100644 ---- a/bin/weeplot/utilities.py -+++ b/bin/weeplot/utilities.py -@@ -431,14 +431,20 @@ class ScaledDraw(object): - - def rectangle(self, box, **options): - """Draw a scaled rectangle. -- -- box: A pair of 2-way tuples, containing coordinates of opposing corners -- of the box. -- -+ -+ box: A pair of 2-way tuples for the lower-left, then upper-right corners of -+ the box [(llx, lly), (urx, ury)] -+ - options: passed on to draw.rectangle. Usually contains 'fill' (the color) - """ -- box_scaled = [(coord[0] * self.xscale + self.xoffset + 0.5, -- coord[1] * self.yscale + self.yoffset + 0.5) for coord in box] -+ # Unpack the box -+ (llsx, llsy), (ursx, ursy) = box -+ -+ ulix = int(llsx * self.xscale + self.xoffset + 0.5) -+ uliy = int(ursy * self.yscale + self.yoffset + 0.5) -+ lrix = int(ursx * self.xscale + self.xoffset + 0.5) -+ lriy = int(llsy * self.yscale + self.yoffset + 0.5) -+ box_scaled = ((ulix, uliy), (lrix, lriy)) - self.draw.rectangle(box_scaled, **options) - - def vector(self, x, vec, vector_rotate, **options): diff --git a/wee_config b/wee_config deleted file mode 100644 index d5c7d44145d6..000000000000 --- a/wee_config +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=wee_config - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* diff --git a/wee_database b/wee_database deleted file mode 100644 index 6267ae332d85..000000000000 --- a/wee_database +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=wee_database - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* diff --git a/wee_debug b/wee_debug deleted file mode 100644 index 82e8aef58f7e..000000000000 --- a/wee_debug +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=wee_debug - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* diff --git a/wee_device b/wee_device deleted file mode 100644 index 99788679332f..000000000000 --- a/wee_device +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=wee_device - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* diff --git a/wee_extension b/wee_extension deleted file mode 100644 index b9d58941f3f8..000000000000 --- a/wee_extension +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=wee_extension - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* diff --git a/wee_import b/wee_import deleted file mode 100644 index 487283c1be11..000000000000 --- a/wee_import +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=wee_import - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* diff --git a/wee_reports b/wee_reports deleted file mode 100644 index fba70fe8303d..000000000000 --- a/wee_reports +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=wee_reports - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* diff --git a/weewx-version.patch b/weewx-version.patch deleted file mode 100644 index 22d99178e79a..000000000000 --- a/weewx-version.patch +++ /dev/null @@ -1,39 +0,0 @@ -diff --git a/bin/weewx/__init__.py b/bin/weewx/__init__.py -index e97c4d8b..436fd783 100644 ---- a/bin/weewx/__init__.py -+++ b/bin/weewx/__init__.py -@@ -7,7 +7,7 @@ - from __future__ import absolute_import - import time - --__version__="4.10.1" -+__version__="4.10.2" - - # Holds the program launch time in unix epoch seconds: - # Useful for calculating 'uptime.' -diff --git a/setup.py b/setup.py -index 93e295b9..256b303e 100755 ---- a/setup.py -+++ b/setup.py -@@ -32,7 +32,7 @@ from distutils.command.install_lib import install_lib - from distutils.core import setup - from distutils.debug import DEBUG - --VERSION = "4.10.1" -+VERSION = "4.10.2" - - if sys.version_info < (2, 7): - log.fatal('WeeWX requires Python V2.7 or greater.') -diff --git a/weewx.conf b/weewx.conf -index 517af0b9..cd98bac6 100644 ---- a/weewx.conf -+++ b/weewx.conf -@@ -20,7 +20,7 @@ log_success = True - log_failure = True - - # Do not modify this. It is used when installing and updating weewx. --version = 4.10.1 -+version = 4.10.2 - - ############################################################################## - diff --git a/weewx.service b/weewx.service index f648519c454f..9517eebeaecf 100644 --- a/weewx.service +++ b/weewx.service @@ -1,14 +1,15 @@ [Unit] -Description=weewx weather system +Description=WeeWX weather system Requires=time-sync.target After=time-sync.target -RequiresMountsFor=/etc /var/lib +RequiresMountsFor=/etc/weewx /var/lib/weewx /var/lib/weewx/www [Service] ExecStart=/usr/bin/weewxd /etc/weewx/weewx.conf StandardOutput=null -#User=weewx -#Group=weewx +StandardError=journal +User=weewx +Group=weewx [Install] WantedBy=multi-user.target diff --git a/weewx.sysusers b/weewx.sysusers new file mode 100755 index 000000000000..15bb4655e47f --- /dev/null +++ b/weewx.sysusers @@ -0,0 +1,3 @@ +# WeeWX System User Definition +#Type Name ID GECOS Home directory Shell +u weewx - "WeeWX weather system" /var/lib/weewx - diff --git a/weewx.tmpfiles b/weewx.tmpfiles new file mode 100755 index 000000000000..14a5a35660a0 --- /dev/null +++ b/weewx.tmpfiles @@ -0,0 +1,4 @@ +# WeeWX directory permissions +#Type Path Mode User Group Age Argument… +d /var/lib/weewx 750 weewx weewx - +d /var/lib/weewx/www 755 weewx weewx - diff --git a/weewxd b/weewxd deleted file mode 100644 index a288cdcdb317..000000000000 --- a/weewxd +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=weewxd - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* diff --git a/wunderfixer b/wunderfixer deleted file mode 100644 index 2aeb62bc4c55..000000000000 --- a/wunderfixer +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -app=wunderfixer - -WEEWX_BINDIR=/usr/lib/weewx -WEEWX_PYTHON=python -$WEEWX_PYTHON $WEEWX_BINDIR/$app $* |