Beispiel #1
0
 def calc_windrun(self, data, data_type):
     """Calculate the wind run since the beginning of the day.  Convert to
     US if necessary since this service operates in US unit system."""
     # calculate windrun only for archive packets
     if data_type == 'loop':
         return
     ets = data['dateTime']
     sts = weeutil.weeutil.startOfDay(ets)
     try:
         run = 0.0
         dbmanager = self.db_binder.get_manager(self.binding)
         for row in dbmanager.genSql(
                 "SELECT `interval`,windSpeed,usUnits"
                 " FROM %s"
                 " WHERE dateTime>? AND dateTime<=?" % dbmanager.table_name,
             (sts, ets)):
             if row is None or None in row:
                 continue
             if row[1]:
                 inc_hours = row[0] / 60.0
                 if row[2] == weewx.METRICWX:
                     run += mps_to_mph(row[1]) * inc_hours
                 elif row[2] == weewx.METRIC:
                     run += kph_to_mph(row[1]) * inc_hours
                 else:
                     run += row[1] * inc_hours
         data['windrun'] = run
     except weedb.DatabaseError:
         pass
Beispiel #2
0
 def calc_windrun(self, data, data_type):
     """Calculate the wind run since the beginning of the day.  Convert to
     US if necessary since this service operates in US unit system."""
     # calculate windrun only for archive packets
     if data_type == 'loop':
         return
     ets = data['dateTime']
     sts = weeutil.weeutil.startOfDay(ets)
     try:
         run = 0.0
         dbmanager = self.db_binder.get_manager(self.binding)
         for row in dbmanager.genSql("SELECT `interval`,windSpeed,usUnits"
                                     " FROM %s"
                                     " WHERE dateTime>? AND dateTime<=?" %
                                     dbmanager.table_name, (sts, ets)):
             if row is None or None in row:
                 continue
             if row[1]:
                 inc_hours = row[0] / 60.0
                 if row[2] == weewx.METRICWX:
                     run += mps_to_mph(row[1]) * inc_hours
                 elif row[2] == weewx.METRIC:
                     run += kph_to_mph(row[1]) * inc_hours
                 else:
                     run += row[1] * inc_hours
         data['windrun'] = run
     except weedb.DatabaseError:
         pass
Beispiel #3
0
def thw_Metric(t_C, RH, ws_kph):
    """ Uses the air temperature, relative humidity, and wind speed
    (THW = temperature-humidity-wind) to calculate a
    potentially more accurate "felt-air temperature." This is not as accurate, however, as the THSW index, which
    can only be calculated when solar radiation information is available. It uses `calculate_heat_index` and then
    applies additional calculations to it using the wind speed. As such, it returns `None` for input temperatures below
    70 degrees Fahrenheit. The additional calculations come from web forums rumored to contain the proprietary
    Davis Instruments THW index formulas.
    hi is the heat index as calculated by `calculate_heat_index`
    WS is the wind speed in miles per hour
    :param temperature: The temperature in degrees Fahrenheit
    :type temperature: int | long | decimal.Decimal
    :param relative_humidity: The relative humidity as a percentage (88.2 instead of 0.882)
    :type relative_humidity: int | long | decimal.Decimal
    :param wind_speed: The wind speed in miles per hour
    :type wind_speed: int | long | decimal.Decimal
    :return: The THW index temperature in degrees Fahrenheit to one decimal place, or `None` if the temperature is
     less than 70F
    :rtype: decimal.Decimal
    """
    t_F = CtoF(t_C)
    hi_F = heatindexF(t_F, RH)
    WS = kph_to_mph(ws_kph)

    if not hi_F:
        return None

    hi = hi_F - (1.072 * WS)
    thw_C = FtoC(hi)

    return round(thw_C, 1) if thw_C is not None else None
Beispiel #4
0
    def _decodeWindSpeed(s):
        # wnnn[K|L|M]nnnD Wind Average
        # <Wnnn[K|L|M] nnnD Wind Gust High
        # A '<' or '>' symbol at the begining of the buffer indicates
        # that this is a high or low reading. The rest of the message
        # decodes the same at the average or gust messages.
        if (s[0] == '<') or (s[0] == '>'):
            s = s[1:]

        try:
            isKnots = (s[4] == 'K')
            isMPH = (s[4] == 'M')
            isKPH = (s[4] == 'L')

            windSpeed = int(s[1:4])
            if isKnots:
                windSpeed *= MILE_PER_KNOT
            elif isKPH:
                windSpeed = kph_to_mph(windSpeed)
            elif isMPH:
                pass

        except Exception:
            logerr("conversion of buffer failed: %s" % s)
            windSpeed = None

        return windSpeed
Beispiel #5
0
    def calc_ET(self, data, data_type):
        """Get maximum and minimum temperatures and average radiation and
        wind speed for the indicated period then calculate the amount of
        evapotranspiration during the interval.  Convert to US units if necessary
        since this service operates in US unit system."""
        # calculate ET only for archive packets
        if data_type != 'archive':
            return
        end_ts = data['dateTime']
        start_ts = end_ts - self.et_period
        interval = self._get_archive_interval(data)
        try:
            dbmanager = self.db_binder.get_manager(self.binding)
            r = dbmanager.getSql(
                "SELECT"
                " MAX(outTemp), MIN(outTemp), AVG(radiation), AVG(windSpeed),"
                " MAX(outHumidity), MIN(outHumidity), MAX(usUnits), MIN(usUnits)"
                " FROM %s WHERE dateTime>? AND dateTime <=?" %
                dbmanager.table_name, (start_ts, end_ts))
            # Make sure everything is there:
            if r is None or None in r:
                data['ET'] = None
                return
            # Unpack the results
            T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit_min, std_unit_max = r
            # Check for mixed units
            if std_unit_min != std_unit_max:
                syslog.syslog(
                    syslog.LOG_NOTICE,
                    "wxservices: Mixed unit system not allowed in ET calculation"
                )
                data['ET'] = None
                return
            std_unit = std_unit_min
            if std_unit == weewx.METRIC or std_unit == weewx.METRICWX:
                T_max = CtoF(T_max)
                T_min = CtoF(T_min)
                if std_unit == weewx.METRICWX:
                    wind_avg = mps_to_mph(wind_avg)
                else:
                    wind_avg = kph_to_mph(wind_avg)
            # Wind height is in meters, so convert it:
            height_ft = self.wind_height / METER_PER_FOOT

            ET_rate = weewx.wxformulas.evapotranspiration_US(
                T_min, T_max, rh_min, rh_max, rad_avg, wind_avg, height_ft,
                self.latitude, self.longitude, self.altitude_ft, end_ts)
            # The formula returns inches/hour. We need the total ET over the
            # archive interval, so multiply by the length of the archive
            # interval in hours.
            data[
                'ET'] = ET_rate * interval / 3600.0 if ET_rate is not None else None
        except ValueError as e:
            weeutil.weeutil.log_traceback()
            syslog.syslog(
                syslog.LOG_ERR,
                "wxservices: Calculation of evapotranspiration failed: %s" % e)
        except weedb.DatabaseError:
            pass
Beispiel #6
0
    def calc_ET(self, data, data_type):
        """Get maximum and minimum temperatures and average radiation and
        wind speed for the indicated period then calculate the amount of
        evapotranspiration during the interval.  Convert to US units if necessary
        since this service operates in US unit system."""
        # calculate ET only for archive packets
        if data_type != 'archive':
            return
        end_ts = data['dateTime']
        start_ts = end_ts - self.et_period
        interval = self._get_archive_interval(data)
        try:
            dbmanager = self.db_binder.get_manager(self.binding)
            r = dbmanager.getSql(
                "SELECT"
                " MAX(outTemp), MIN(outTemp), AVG(radiation), AVG(windSpeed),"
                " MAX(outHumidity), MIN(outHumidity), MAX(usUnits), MIN(usUnits)"
                " FROM %s WHERE dateTime>? AND dateTime <=?"
                % dbmanager.table_name, (start_ts, end_ts))
            # Make sure everything is there:
            if r is None or None in r:
                data['ET'] = None
                return
            # Unpack the results
            T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit_min, std_unit_max = r
            # Check for mixed units
            if std_unit_min != std_unit_max:
                syslog.syslog(syslog.LOG_NOTICE, "wxservices: Mixed unit system not allowed in ET calculation")
                data['ET'] = None
                return
            std_unit = std_unit_min
            if std_unit == weewx.METRIC or std_unit == weewx.METRICWX:
                T_max = CtoF(T_max)
                T_min = CtoF(T_min)
                if std_unit == weewx.METRICWX:
                    wind_avg = mps_to_mph(wind_avg)
                else:
                    wind_avg = kph_to_mph(wind_avg)
            # Wind height is in meters, so convert it:
            height_ft = self.wind_height / METER_PER_FOOT

            ET_rate = weewx.wxformulas.evapotranspiration_US(T_min, T_max, 
                                                             rh_min, rh_max, 
                                                             rad_avg, wind_avg, height_ft, 
                                                             self.latitude, self.longitude, self.altitude_ft, 
                                                             end_ts)
            # The formula returns inches/hour. We need the total ET over the archive
            # interval, so multiply by the length of the archive interval in hours.
            data['ET'] = ET_rate * interval / 3600.0 if ET_rate is not None else None
        except ValueError, e:
            weeutil.weeutil.log_traceback()
            syslog.syslog(syslog.LOG_ERR, "wxservices: Calculation of evapotranspiration failed: %s" % e)
Beispiel #7
0
 def calc_ET(self, data, data_type):
     """Get maximum and minimum temperatures and average radiation and
     wind speed for the indicated period then calculate the amount of
     evapotranspiration during the interval.  Convert to US units if necessary
     since this service operates in US unit system."""
     # calculate ET only for archive packets
     if data_type != 'archive':
         return
     end_ts = data['dateTime']
     start_ts = end_ts - self.et_period
     interval = self._get_archive_interval(data)
     try:
         dbmanager = self.db_binder.get_manager(self.binding)
         r = dbmanager.getSql(
             "SELECT"
             " MAX(outTemp), MIN(outTemp), AVG(radiation), AVG(windSpeed),"
             " MAX(outHumidity), MIN(outHumidity), usUnits"
             " FROM %s WHERE dateTime>? AND dateTime <=?" %
             dbmanager.table_name, (start_ts, end_ts))
         if r is None:
             data['ET'] = None
             return
         # Unpack the results
         T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit = r
         # Check for null values. Null relative humidity is OK.
         if T_max is None or T_min is None or rad_avg is None or wind_avg is None or std_unit is None:
             data['ET'] = None
             return
         if std_unit == weewx.METRIC or std_unit == weewx.METRICWX:
             T_max = CtoF(T_max)
             T_min = CtoF(T_min)
             if std_unit == weewx.METRICWX:
                 wind_avg = mps_to_mph(wind_avg)
             else:
                 wind_avg = kph_to_mph(wind_avg)
         # Rate will be in inches per day
         ET_rate = weewx.wxformulas.evapotranspiration_US(
             T_max, T_min, rad_avg, wind_avg, self.wind_height,
             self.latitude, data['dateTime'], rh_min, rh_max)
         # Multiply the ET rate by the length of the interval in days.
         # This will give the total amount of ET during the archive interval.
         data['ET'] = ET_rate * interval / (
             24 * 3600.0) if ET_rate is not None else None
     except ValueError, e:
         weeutil.weeutil.log_traceback()
         syslog.syslog(
             syslog.LOG_ERR,
             "wxservices: Calculation of evapotranspiration failed: %s" % e)
Beispiel #8
0
 def calc_ET(self, data, data_type):
     """Get maximum and minimum temperatures and average radiation and
     wind speed for the indicated period then calculate the amount of
     evapotranspiration during the interval.  Convert to US units if necessary
     since this service operates in US unit system."""
     # calculate ET only for archive packets
     if data_type != 'archive':
         return
     end_ts = data['dateTime']
     start_ts = end_ts - self.et_period
     interval = self._get_archive_interval(data)
     try:
         dbmanager = self.db_binder.get_manager(self.binding)
         r = dbmanager.getSql(
             "SELECT"
             " MAX(outTemp), MIN(outTemp), AVG(radiation), AVG(windSpeed),"
             " MAX(outHumidity), MIN(outHumidity), usUnits"
             " FROM %s WHERE dateTime>? AND dateTime <=?"
             % dbmanager.table_name, (start_ts, end_ts))
         if r is None:
             data['ET'] = None
             return
         # Unpack the results
         T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit = r
         # Check for null values. Null relative humidity is OK.
         if T_max is None or T_min is None or rad_avg is None or wind_avg is None or std_unit is None:
             data['ET'] = None
             return
         if std_unit == weewx.METRIC or std_unit == weewx.METRICWX:
             T_max = CtoF(T_max)
             T_min = CtoF(T_min)
             if std_unit == weewx.METRICWX:
                 wind_avg = mps_to_mph(wind_avg)
             else:
                 wind_avg = kph_to_mph(wind_avg)
         # Rate will be in inches per day
         ET_rate = weewx.wxformulas.evapotranspiration_US(
                       T_max, T_min, rad_avg, wind_avg,
                       self.wind_height, self.latitude,
                       data['dateTime'], rh_min, rh_max)
         # Multiply the ET rate by the length of the interval in days.
         # This will give the total amount of ET during the archive interval.
         data['ET'] = ET_rate * interval / (24*3600.0) if ET_rate is not None else None
     except ValueError, e:
         weeutil.weeutil.log_traceback()
         syslog.syslog(syslog.LOG_ERR, "wxservices: Calculation of evapotranspiration failed: %s" % e)
Beispiel #9
0
    def get_scalar(self, obs_type, data, db_manager, **option_dict):
        """Calculate ET as a scalar"""
        if obs_type != 'ET':
            raise weewx.UnknownType(obs_type)

        if 'interval' not in data:
            # This will cause LOOP data not to be processed.
            raise weewx.CannotCalculate(obs_type)

        interval = data['interval']
        end_ts = data['dateTime']
        start_ts = end_ts - self.et_period
        try:
            r = db_manager.getSql(
                "SELECT MAX(outTemp), MIN(outTemp), "
                "AVG(radiation), AVG(windSpeed), "
                "MAX(outHumidity), MIN(outHumidity), "
                "MAX(usUnits), MIN(usUnits) FROM %s "
                "WHERE dateTime>? AND dateTime <=?" % db_manager.table_name,
                (start_ts, end_ts))
        except weedb.DatabaseError:
            return ValueTuple(None, None, None)

        # Make sure everything is there:
        if r is None or None in r:
            return ValueTuple(None, None, None)

        # Unpack the results
        T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit_min, std_unit_max = r

        # Check for mixed units
        if std_unit_min != std_unit_max:
            log.info(
                "Mixed unit system not allowed in ET calculation. Skipped.")
            return ValueTuple(None, None, None)
        std_unit = std_unit_min
        if std_unit == weewx.METRIC or std_unit == weewx.METRICWX:
            T_max = CtoF(T_max)
            T_min = CtoF(T_min)
            if std_unit == weewx.METRICWX:
                wind_avg = mps_to_mph(wind_avg)
            else:
                wind_avg = kph_to_mph(wind_avg)
        # Wind height is in meters, so convert it:
        height_ft = self.wind_height / METER_PER_FOOT
        # Get altitude in feet
        altitude_ft = weewx.units.convert(self.altitude_vt, 'foot')[0]

        try:
            ET_rate = weewx.wxformulas.evapotranspiration_US(
                T_min, T_max, rh_min, rh_max, rad_avg, wind_avg, height_ft,
                self.latitude_f, self.longitude_f, altitude_ft, end_ts,
                self.albedo, self.cn, self.cd)
        except ValueError as e:
            log.error("Calculation of evapotranspiration failed: %s", e)
            weeutil.logger.log_traceback(log.error)
            ET_inch = None
        else:
            # The formula returns inches/hour. We need the total ET over the interval, so multiply
            # by the length of the interval in hours. Remember that 'interval' is actually in
            # minutes.
            ET_inch = ET_rate * interval / 60.0 if ET_rate is not None else None

        return ValueTuple(ET_inch, 'inch', 'group_rain')
Beispiel #10
0
    def calc_ET(self, key, data, db_manager):
        """Get maximum and minimum temperatures and average radiation and
        wind speed for the indicated period then calculate the amount of
        evapotranspiration during the interval.  Convert to US units if necessary
        since this service operates in US unit system."""

        if 'interval' not in data:
            # This will cause LOOP data not to be processed.
            raise weewx.CannotCalculate(key)

        interval = data['interval']
        end_ts = data['dateTime']
        start_ts = end_ts - self.et_period
        try:
            r = db_manager.getSql(
                "SELECT MAX(outTemp), MIN(outTemp), "
                "AVG(radiation), AVG(windSpeed), "
                "MAX(outHumidity), MIN(outHumidity), "
                "MAX(usUnits), MIN(usUnits) FROM %s WHERE dateTime>? AND dateTime <=?"
                % db_manager.table_name, (start_ts, end_ts))
        except weedb.DatabaseError:
            return ValueTuple(None, None, None)

        # Make sure everything is there:
        if r is None or None in r:
            return ValueTuple(None, None, None)

        # Unpack the results
        T_max, T_min, rad_avg, wind_avg, rh_max, rh_min, std_unit_min, std_unit_max = r

        # Check for mixed units
        if std_unit_min != std_unit_max:
            log.info(
                "Mixed unit system not allowed in ET calculation. Skipped.")
            return ValueTuple(None, None, None)
        std_unit = std_unit_min
        if std_unit == weewx.METRIC or std_unit == weewx.METRICWX:
            T_max = CtoF(T_max)
            T_min = CtoF(T_min)
            if std_unit == weewx.METRICWX:
                wind_avg = mps_to_mph(wind_avg)
            else:
                wind_avg = kph_to_mph(wind_avg)
        # Wind height is in meters, so convert it:
        height_ft = self.wind_height / METER_PER_FOOT
        # Get altitude in feet
        altitude_ft = weewx.units.convert(self.altitude_vt, 'foot')[0]

        try:
            ET_rate = weewx.wxformulas.evapotranspiration_US(
                T_min, T_max, rh_min, rh_max, rad_avg, wind_avg, height_ft,
                self.latitude, self.longitude, altitude_ft, end_ts)
        except ValueError as e:
            log.error("Calculation of evapotranspiration failed: %s", e)
            weeutil.logger.log_traceback(log.error)
            ET_inch = None
        else:
            # The formula returns inches/hour. We need the total ET over the interval, so multiply by the length of the
            # interval in hours. Remember that 'interval' is actually in minutes.
            ET_inch = ET_rate * interval / 60.0 if ET_rate is not None else None

        # Convert back to the unit system of the incoming record:
        ET = weewx.units.convertStd((ET_inch, 'inch', 'group_rain'),
                                    data['usUnits'])
        return ET