I looked at the documentation again and providing patches was a topic I
didn't have success locating. Google had the send a diff to the mailing
list for review but that was vintage 2012. If could expand a bit on how to
make a pull request? My SVN repo isn't public. But I can attach the file.
I thought the easy fix is change the order of the tests to most popular to
least. But during install the script could ask and here are three
choices. It's easy for the RPM method since the OS is known. But it would
be also nice if setup.py could figure it out, but at the same time, putting
it in the weewx.conf is also pick one of these choices also making it
easy.
That's beyond my current python skill set, but I also didn't want to go
further without getting better direction/suggestions. Getting the basic
patch
in keeps my upgrade path simple. But at the same time, if there was a port
for FreeBSD, this would solve those what OS selection questions too. The
more I think about it the more I like the port idea for FreeBSD.
On Sunday, December 11, 2016 at 12:30:45 PM UTC-8, Bill Richter wrote:
>
> The inline diff works for me. I'm not a diehard python coder. I'll like
> to have this touched up a bit. While this works, it might not be ideal. I
> don't like the hard coded library path needed for BSD.
>
> * What I'd like is to have the OS installed as a weewx.conf option. Then
> the station.py code could get the OS version and use the correct library
> path and not have keep testing which OS is being used.
>
> * Make setup.py find the correct OS and insert the correct code again,
> keeping station.py from checking on every execution.
>
> * Failing 1 or 2, perhaps the order should be Linux, Freebsd, MacOS?
> This keeps is close to the current configuration.
>
> * I think it might be simple to have Linux pull data from /proc as opposed
> to using the same code as FreeBSD and executing based on the OS detected.
> But I think option 1 and 2 would still be nice. Just install the correct
> code in a stub in station.py.
>
> * I only tested this on FreeBSD. I'm not sure all the
> necessary/recommended error recovery is in place. I think the existing
> code will return NA if one of the three matches isn't found.
>
> # diff --context station.py.orig station.py.new
> *** station.py.orig Tue Dec 6 10:23:34 2016
> --- station.py.new Sun Dec 11 12:20:08 2016
> ***************
> *** 8,13 ****
> --- 8,14 ----
>
> import weeutil.weeutil
> import weewx.units
> + import os, sys, datetime
>
> # For MacOS:
> try:
> ***************
> *** 100,121 ****
> @property
> def os_uptime(self):
> """Lazy evaluation of the server uptime."""
> - # Get the OS uptime. Because this is highly operating system
> dependent, several
> - # different strategies may have to be tried:
> os_uptime_secs = None
> ! try:
> # For Linux:
> ! os_uptime_secs =
> float(open("/proc/uptime").read().split()[0])
> ! except (IOError, KeyError):
> ! try:
> # For MacOs:
> ! os_uptime_secs = CACurrentMediaTime()
> ! except NameError:
> ! pass
> !
> ! return weewx.units.ValueHelper(value_t=(os_uptime_secs,
> "second", "group_deltatime"),
> ! formatter=self.formatter,
> ! converter=self.converter)
>
> def __getattr__(self, name):
> # This is to get around bugs in the Python version of Cheetah's
> namemapper:
> --- 101,146 ----
> @property
> def os_uptime(self):
> """Lazy evaluation of the server uptime."""
> os_uptime_secs = None
> ! try:
> ! import ctypes
> ! class timespec(ctypes.Structure):
> ! _fields_ = [
> ! ('tv_sec', ctypes.c_long), ('tv_nsec', ctypes.c_long)
> ! ]
> !
> ! if sys.platform.startswith('freebsd'):
> ! CLOCK_MONOTONIC = 4# see < time.h >
> ! dylib = 'libc.so.7'
> ! #else :
> ! # sys.platform.startswith('linux')
> ! # CLOCK_MONOTONIC = 1# see < linux / time.h >
> ! # dylib = 'librt.so.1'
> !
> ! syslib = ctypes.CDLL(dylib, use_errno = True)
> ! clock_gettime = syslib.clock_gettime
> ! clock_gettime.argtypes = [ctypes.c_int,
> ctypes.POINTER(timespec)]
> ! t = timespec()
> !
> ! if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
> ! errno_ = ctypes.get_errno()
> ! raise OSError(errno_, os.strerror(errno_))
> ! os_uptime_secs = t.tv_sec + t.tv_nsec * 1e-9
> !
> ! except ImportError:
> ! try:
> # For Linux:
> ! os_uptime_secs =
> float(open("/proc/uptime").read().split()[0])
> ! except (IOError, KeyError):
> ! try:
> # For MacOs:
> ! os_uptime_secs = CACurrentMediaTime()
> ! except NameError:
> ! pass
> !
> ! return weewx.units.ValueHelper(value_t=(os_uptime_secs,
> "second", "group_deltatime"),
> ! formatter=self.formatter,
> ! converter=self.converter)
>
> def __getattr__(self, name):
> # This is to get around bugs in the Python version of Cheetah's
> namemapper:
>
#
# Copyright (c) 2009-2015 Tom Keffer <[email protected]>
#
# See the file LICENSE.txt for your full rights.
#
#$Id: station.py 1117 2016-12-13 01:30:53Z richterb $
"""Defines (mostly static) information about a station."""
import time
import weeutil.weeutil
import weewx.units
import os, sys, datetime
# For MacOS:
try:
from Quartz.QuartzCore import CACurrentMediaTime
except ImportError:
pass
class StationInfo(object):
"""Readonly class with static station information. It has no formatting information. Just a POS.
Attributes:
altitude_vt: Station altitude as a ValueTuple
hardware: A string holding a hardware description
rain_year_start: The start of the rain year (1=January)
latitude_f: Floating point latitude
longitude_f: Floating point longitude
location: String holding a description of the station location
week_start: The start of the week (0=Monday)
station_url: An URL with an informative website (if any) about the station
"""
def __init__(self, console=None, **stn_dict):
"""Extracts info from the console and stn_dict and stores it in self."""
if console and hasattr(console, "altitude_vt"):
self.altitude_vt = console.altitude_vt
else:
altitude_t = weeutil.weeutil.option_as_list(stn_dict.get('altitude', (None, None)))
try:
self.altitude_vt = weewx.units.ValueTuple(float(altitude_t[0]), altitude_t[1], "group_altitude")
except KeyError, e:
raise weewx.ViolatedPrecondition("Value 'altitude' needs a unit (%s)" % e)
if console and hasattr(console, 'hardware_name'):
self.hardware = console.hardware_name
else:
self.hardware = stn_dict.get('station_type', 'Unknown')
if console and hasattr(console, 'rain_year_start'):
self.rain_year_start = getattr(console, 'rain_year_start')
else:
self.rain_year_start = int(stn_dict.get('rain_year_start', 1))
self.latitude_f = float(stn_dict['latitude'])
self.longitude_f = float(stn_dict['longitude'])
# Locations frequently have commas in them. Guard against ConfigObj turning it into a list:
self.location = weeutil.weeutil.list_as_string(stn_dict.get('location', 'Unknown'))
self.week_start = int(stn_dict.get('week_start', 6))
self.station_url = stn_dict.get('station_url')
# For backwards compatibility:
self.webpath = self.station_url
class Station(object):
"""Formatted version of StationInfo."""
def __init__(self, stn_info, formatter, converter, skin_dict):
# Store away my instance of StationInfo
self.stn_info = stn_info
self.formatter = formatter
self.converter = converter
# Add a bunch of formatted attributes:
label_dict = skin_dict.get('Labels', {})
hemispheres = label_dict.get('hemispheres', ('N','S','E','W'))
latlon_formats = label_dict.get('latlon_formats')
self.latitude = weeutil.weeutil.latlon_string(stn_info.latitude_f,
hemispheres[0:2],
'lat', latlon_formats)
self.longitude = weeutil.weeutil.latlon_string(stn_info.longitude_f,
hemispheres[2:4],
'lon', latlon_formats)
self.altitude = weewx.units.ValueHelper(value_t=stn_info.altitude_vt,
formatter=formatter,
converter=converter)
self.rain_year_str = time.strftime("%b", (0, self.rain_year_start, 1, 0,0,0,0,0,-1))
self.version = weewx.__version__
@property
def uptime(self):
"""Lazy evaluation of weewx uptime."""
delta_time = time.time() - weewx.launchtime_ts if weewx.launchtime_ts else None
return weewx.units.ValueHelper(value_t=(delta_time, "second", "group_deltatime"),
formatter=self.formatter,
converter=self.converter)
@property
def os_uptime(self):
"""Lazy evaluation of the server uptime."""
# Get the OS uptime. Because this is highly operating system dependent, several
# different strategies may have to be tried:
os_uptime_secs = None
try:
import ctypes
class timespec(ctypes.Structure):
_fields_ = [
('tv_sec', ctypes.c_long), ('tv_nsec', ctypes.c_long)
]
if sys.platform.startswith('freebsd'):
CLOCK_MONOTONIC = 4# see < time.h >
dylib = 'libc.so.7'
#else :
# sys.platform.startswith('linux')
# CLOCK_MONOTONIC = 1# see < linux / time.h >
# dylib = 'librt.so.1'
syslib = ctypes.CDLL(dylib, use_errno = True)
clock_gettime = syslib.clock_gettime
clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
t = timespec()
if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
errno_ = ctypes.get_errno()
raise OSError(errno_, os.strerror(errno_))
os_uptime_secs = t.tv_sec + t.tv_nsec * 1e-9
except ImportError:
try:
# For Linux:
os_uptime_secs = float(open("/proc/uptime").read().split()[0])
except (IOError, KeyError):
try:
# For MacOs:
os_uptime_secs = CACurrentMediaTime()
except NameError:
pass
return weewx.units.ValueHelper(value_t=(os_uptime_secs, "second", "group_deltatime"),
formatter=self.formatter,
converter=self.converter)
def __getattr__(self, name):
# This is to get around bugs in the Python version of Cheetah's namemapper:
if name in ['__call__', 'has_key']:
raise AttributeError
# For anything that is not an explicit attribute of me, try
# my instance of StationInfo.
return getattr(self.stn_info, name)