Exemplo n.º 1
0
    def calculate_balances(self):
        from scheduler import predicted_schedule
        now = datetime.datetime.now()
        for station in stations.get():
            station.balance = {
                key: value
                for key, value in station.balance.iteritems()
                if key >= now.date() - datetime.timedelta(days=21)
            }

            if not station.balance or (now.date() - datetime.timedelta(days=21)
                                       ) not in station.balance:
                station.balance[now.date() - datetime.timedelta(days=21)] = {
                    'eto': 0.0,
                    'rain': 0.0,
                    'intervals': [],
                    'total': 0.0,
                    'valid': True
                }

            runs = log.finished_runs() + log.active_runs()
            calc_day = now.date() - datetime.timedelta(days=20)
            while calc_day < now.date() + datetime.timedelta(days=10):
                if calc_day not in station.balance:
                    station.balance[calc_day] = {
                        'eto': 4.0,
                        'rain': 0.0,
                        'intervals': [],
                        'total': 0.0,
                        'valid': False
                    }
                try:
                    if not station.balance[calc_day][
                            'valid'] or calc_day >= now.date():
                        station.balance[calc_day]['eto'] = weather.get_eto(
                            calc_day)
                        station.balance[calc_day]['rain'] = weather.get_rain(
                            calc_day)
                        station.balance[calc_day]['valid'] = True
                except Exception:
                    station.balance[calc_day]['valid'] = False
                    logging.warning(
                        'Could not get weather information, using fallbacks:\n'
                        + traceback.format_exc())

                intervals = []
                while runs and runs[0]['start'].date() <= calc_day:
                    run = runs[0]
                    if runs[0]['start'].date() == calc_day and not run[
                            'blocked'] and run['station'] == station.index:
                        irrigation = (run['end'] - run['start']).total_seconds(
                        ) / 3600 * station.precipitation
                        if run['manual']:
                            irrigation *= 0.5  # Only count half in case of manual runs
                        intervals.append({
                            'program': run['program'],
                            'program_name': run['program_name'],
                            'done': True,
                            'irrigation': irrigation
                        })
                    del runs[0]

                if calc_day >= now.date():
                    if calc_day == now.date():
                        date_time_start = now
                    else:
                        date_time_start = datetime.datetime.combine(
                            calc_day, datetime.time.min)
                    date_time_end = datetime.datetime.combine(
                        calc_day, datetime.time.max)
                    for run in predicted_schedule(date_time_start,
                                                  date_time_end):
                        if not run['blocked'] and run[
                                'station'] == station.index:
                            irrigation = (
                                run['end'] - run['start']
                            ).total_seconds() / 3600 * station.precipitation
                            intervals.append({
                                'program':
                                run['program'],
                                'program_name':
                                run['program_name'],
                                'done':
                                False,
                                'irrigation':
                                irrigation
                            })

                if len(intervals) > len(station.balance[calc_day]['intervals']
                                        ) or calc_day >= now.date():
                    station.balance[calc_day]['intervals'] = intervals

                station.balance[calc_day]['total'] = station.balance[calc_day - datetime.timedelta(days=1)]['total'] \
                                                     - station.balance[calc_day]['eto'] \
                                                     + station.balance[calc_day]['rain'] \
                                                     + sum(interval['irrigation'] for interval in station.balance[calc_day]['intervals'])

                station.balance[calc_day]['total'] = max(
                    -100,
                    min(station.balance[calc_day]['total'], station.capacity))

                calc_day += datetime.timedelta(days=1)

            station.balance = station.balance  # Force saving
Exemplo n.º 2
0
    def run(self):
        weather.add_callback(self.update)
        self._sleep(10)  # Wait for weather callback before starting
        while not self._stop_event.is_set():
            try:
                log.clear(NAME)
                if plugin_options['enabled']:
                    log.debug(NAME, _(u'Checking weather status') + '...')

                    info = []
                    days = 0
                    total_info = {'rain_mm': 0.0}
                    for day in range(-plugin_options['days_history'],
                                     plugin_options['days_forecast'] + 1):
                        check_date = datetime.date.today(
                        ) + datetime.timedelta(days=day)
                        hourly_data = weather.get_hourly_data(check_date)
                        if hourly_data:
                            days += 1
                        info += hourly_data

                        total_info['rain_mm'] += weather.get_rain(check_date)

                    log.info(
                        NAME,
                        _(u'Using') + ' %d ' % days +
                        _(u'days of information.'))

                    total_info.update({
                        'temp_c':
                        sum([val['temperature'] for val in info]) / len(info),
                        'wind_ms':
                        sum([val['windSpeed'] for val in info]) / len(info),
                        'humidity':
                        sum([val['humidity'] for val in info]) / len(info)
                    })

                    # We assume that the default 100% provides 4mm water per day (normal need)
                    # We calculate what we will need to provide using the mean data of X days around today

                    water_needed = 4 * days  # 4mm per day
                    water_needed *= 1 + (total_info['temp_c'] -
                                         20) / 15  # 5 => 0%, 35 => 200%
                    water_needed *= 1 + (total_info['wind_ms'] / 100
                                         )  # 0 => 100%, 20 => 120%
                    water_needed *= 1 - (total_info['humidity'] -
                                         50) / 200  # 0 => 125%, 100 => 75%
                    water_needed = round(water_needed, 1)

                    water_left = water_needed - total_info['rain_mm']
                    water_left = round(max(0, min(100, water_left)), 1)

                    water_adjustment = round((water_left / (4 * days)) * 100,
                                             1)

                    water_adjustment = float(
                        max(plugin_options['wl_min'],
                            min(plugin_options['wl_max'], water_adjustment)))

                    log.info(
                        NAME,
                        _(u'Water needed') + ' %d ' % days + _('days') +
                        ': %.1fmm' % water_needed)
                    log.info(
                        NAME,
                        _(u'Total rainfall') +
                        ': %.1fmm' % total_info['rain_mm'])
                    log.info(NAME, u'_______________________________')
                    log.info(NAME,
                             _(u'Irrigation needed') + ': %.1fmm' % water_left)
                    log.info(
                        NAME,
                        _(u'Weather Adjustment') +
                        ': %.1f%%' % water_adjustment)

                    level_adjustments[NAME] = water_adjustment / 100

                    if plugin_options['protect_enabled']:
                        current_data = weather.get_current_data()
                        temp_local_unit = current_data[
                            'temperature'] if options.temp_unit == "C" else 32.0 + 9.0 / 5.0 * current_data[
                                'temperature']
                        log.debug(
                            NAME,
                            _(u'Temperature') + ': %.1f %s' %
                            (temp_local_unit, options.temp_unit))
                        month = time.localtime().tm_mon  # Current month.
                        if temp_local_unit < plugin_options[
                                'protect_temp'] and month in plugin_options[
                                    'protect_months']:
                            station_seconds = {}
                            for station in stations.enabled_stations():
                                if station.index in plugin_options[
                                        'protect_stations']:
                                    station_seconds[
                                        station.index] = plugin_options[
                                            'protect_minutes'] * 60
                                else:
                                    station_seconds[station.index] = 0

                            for station in stations.enabled_stations():
                                if run_once.is_active(datetime.datetime.now(),
                                                      station.index):
                                    break
                            else:
                                log.debug(NAME, _(u'Protection activated.'))
                                run_once.set(station_seconds)

                    self._sleep(3600)

                else:
                    log.clear(NAME)
                    log.info(NAME, _(u'Plug-in is disabled.'))
                    if NAME in level_adjustments:
                        del level_adjustments[NAME]
                    self._sleep(24 * 3600)

            except Exception:
                log.error(
                    NAME,
                    _(u'Weather-based water level plug-in') + ':\n' +
                    traceback.format_exc())
                self._sleep(3600)
        weather.remove_callback(self.update)
Exemplo n.º 3
0
    def calculate_balances(self):
        from scheduler import predicted_schedule
        now = datetime.datetime.now()
        for station in stations.get():
            station.balance = {key: value for key, value in station.balance.iteritems()
                               if key >= now.date() - datetime.timedelta(days=21)}

            if not station.balance or (now.date() - datetime.timedelta(days=21)) not in station.balance:
                station.balance[now.date() - datetime.timedelta(days=21)] = {
                    'eto': 0.0,
                    'rain': 0.0,
                    'intervals': [],
                    'total': 0.0,
                    'valid': True
                }

            runs = log.finished_runs() + log.active_runs()
            calc_day = now.date() - datetime.timedelta(days=20)
            while calc_day < now.date() + datetime.timedelta(days=7):
                if calc_day not in station.balance:
                    station.balance[calc_day] = {
                        'eto': 4.0,
                        'rain': 0.0,
                        'intervals': [],
                        'total': 0.0,
                        'valid': False
                    }
                try:
                    if not station.balance[calc_day]['valid'] or calc_day >= now.date() - datetime.timedelta(days=1):
                        station.balance[calc_day]['eto'] = station.eto_factor * weather.get_eto(calc_day)
                        station.balance[calc_day]['rain'] = 0.0 if station.ignore_rain else weather.get_rain(calc_day)
                        station.balance[calc_day]['valid'] = True
                except Exception:
                    station.balance[calc_day]['valid'] = False
                    logging.warning('Could not get weather information, using fallbacks:\n' + traceback.format_exc())

                intervals = []
                while runs and runs[0]['start'].date() <= calc_day:
                    run = runs[0]
                    if runs[0]['start'].date() == calc_day and not run['blocked'] and run['station'] == station.index:
                        irrigation = (run['end'] - run['start']).total_seconds() / 3600 * station.precipitation
                        if run['manual']:
                            irrigation *= 0.5  # Only count half in case of manual runs
                        intervals.append({
                            'program': run['program'],
                            'program_name': run['program_name'],
                            'done': True,
                            'irrigation': irrigation
                        })
                    del runs[0]

                if calc_day >= now.date():
                    if calc_day == now.date():
                        date_time_start = now
                    else:
                        date_time_start = datetime.datetime.combine(calc_day, datetime.time.min)
                    date_time_end = datetime.datetime.combine(calc_day, datetime.time.max)
                    for run in predicted_schedule(date_time_start, date_time_end):
                        if not run['blocked'] and run['station'] == station.index:
                            irrigation = (run['end'] - run['start']).total_seconds() / 3600 * station.precipitation
                            intervals.append({
                                'program': run['program'],
                                'program_name': run['program_name'],
                                'done': False,
                                'irrigation': irrigation
                            })

                if len(intervals) > len(station.balance[calc_day]['intervals']) or calc_day >= now.date():
                    station.balance[calc_day]['intervals'] = intervals

                station.balance[calc_day]['total'] = station.balance[calc_day - datetime.timedelta(days=1)]['total'] \
                                                     - station.balance[calc_day]['eto'] \
                                                     + station.balance[calc_day]['rain'] \
                                                     + sum(interval['irrigation'] for interval in station.balance[calc_day]['intervals'])

                station.balance[calc_day]['total'] = max(-100, min(station.balance[calc_day]['total'], station.capacity))

                calc_day += datetime.timedelta(days=1)

            station.balance = station.balance # Force saving
Exemplo n.º 4
0
    def run(self):
        weather.add_callback(self.update)
        self._sleep(10)  # Wait for weather callback before starting
        while not self._stop_event.is_set():
            try:
                log.clear(NAME)
                if plugin_options['enabled']:
                    log.debug(NAME, _(u'Checking weather status') + '...')

                    if plugin_options['use_netatmo']:
                        authorization = ClientAuth()
                        devList = WeatherStationData(authorization)
                        now = time.time()
                        begin = now - (
                            plugin_options['days_history']) * 24 * 3600
                        mac2 = plugin_options['netatmomac']
                        rainmac2 = plugin_options['netatmorain']
                        resp = (devList.getMeasure(mac2,
                                                   '1hour',
                                                   'sum_rain',
                                                   rainmac2,
                                                   date_begin=begin,
                                                   date_end=now,
                                                   limit=None,
                                                   optimize=False))
                        result = [(time.ctime(int(k)), v[0])
                                  for k, v in resp['body'].items()]
                        result.sort()
                        xdate, xrain = zip(*result)
                        zrain = 0
                        for yrain in xrain:
                            zrain = zrain + yrain
                    else:
                        zrain = 0

                    info = []
                    days = 0
                    total_info = {'rain_mm': 0.0}
                    for day in range(-plugin_options['days_history'],
                                     plugin_options['days_forecast'] + 1):
                        check_date = datetime.date.today(
                        ) + datetime.timedelta(days=day)
                        hourly_data = weather.get_hourly_data(check_date)
                        if hourly_data:
                            days += 1
                        info += hourly_data

                        total_info['rain_mm'] += weather.get_rain(check_date)

                    log.info(
                        NAME,
                        _(u'Using') + ' %d ' % days +
                        _(u'days of information.'))

                    total_info.update({
                        'temp_c':
                        sum([val['temperature'] for val in info]) / len(info),
                        'wind_ms':
                        sum([val['windSpeed'] for val in info]) / len(info),
                        'humidity':
                        sum([val['humidity'] for val in info]) / len(info)
                    })

                    # We assume that the default 100% provides 4mm water per day (normal need)
                    # We calculate what we will need to provide using the mean data of X days around today

                    water_needed = 4 * days  # 4mm per day
                    water_needed *= 1 + (total_info['temp_c'] -
                                         20) / 15  # 5 => 0%, 35 => 200%
                    water_needed *= 1 + (total_info['wind_ms'] / 100
                                         )  # 0 => 100%, 20 => 120%
                    water_needed *= 1 - (total_info['humidity'] -
                                         50) / 200  # 0 => 125%, 100 => 75%
                    water_needed = round(water_needed, 1)

                    water_left = water_needed - total_info['rain_mm']
                    water_left = round(max(0, min(100, water_left)), 1)

                    water_adjustment = round((water_left / (4 * days)) * 100,
                                             1)

                    level_adjustments[NAME] = water_adjustment / 100

                    if plugin_options['use_netatmo']:
                        water_left = water_needed - zrain - total_info[
                            'rain_mm']
                        water_left = round(max(0, min(100, water_left)), 1)

                    else:
                        water_left = water_needed - total_info['rain_mm']
                        water_left = round(max(0, min(100, water_left)), 1)

                    water_adjustment = round(
                        (water_left /
                         ((plugin_options['netatmo_level']) * days)) * 100, 1)

                    water_adjustment = float(
                        max(plugin_options['wl_min'],
                            min(plugin_options['wl_max'], water_adjustment)))

                    log.info(
                        NAME,
                        _(u'Water needed') + '(%d ' % days + _(u'days') +
                        '): %.1fmm' % water_needed)
                    log.info(
                        NAME,
                        _(u'Total rainfall') +
                        ': %.1fmm' % total_info['rain_mm'])
                    log.info(NAME, _(u'_______________________________'))
                    log.info(NAME,
                             _(u'Irrigation needed') + ': %.1fmm' % water_left)
                    log.info(
                        NAME,
                        _(u'Weather Adjustment') +
                        ': %.1f%%' % water_adjustment)
                    log.info(NAME, _(u'_______________________________'))
                    log.info(
                        NAME,
                        _(u'History rain by Netatmo') + ': %.1fmm' % zrain)

                    self._sleep(3600)

                else:
                    log.clear(NAME)
                    log.info(NAME, _(u'Plug-in is disabled.'))
                    if NAME in level_adjustments:
                        del level_adjustments[NAME]
                    self._sleep(24 * 3600)

            except Exception:
                log.error(
                    NAME,
                    _(u'Weather-based water level plug-in') + ':\n' +
                    traceback.format_exc())
                self._sleep(3600)
        weather.remove_callback(self.update)