Пример #1
0
    def __engine_loop(self):
        time_short = 0
        error_counter = 0
        logger.info('Start terrariumPI engine')
        while self.__running:
            starttime = time.time()

            try:
                # Update weather
                self.weather.update()
                weather_data = self.weather.get_data()
                if 'hour_forecast' in weather_data and len(
                        weather_data['hour_forecast']) > 0:
                    self.collector.log_weather_data(
                        weather_data['hour_forecast'][0])

                # Update sensors
                for sensorid in self.sensors:
                    # Update the current sensor.
                    self.sensors[sensorid].update()
                    # Save new data to database
                    self.collector.log_sensor_data(
                        self.sensors[sensorid].get_data())
                    # Websocket callback
                    self.get_sensors([sensorid], socket=True)
                    # Send notification when needed and enabled
                    if self.sensors[sensorid].is_active(
                    ) and self.sensors[sensorid].notification_enabled(
                    ) and self.sensors[sensorid].get_alarm():
                        self.notification.message(
                            'sensor_alarm_' +
                            ('low' if self.sensors[sensorid].get_current() <
                             self.sensors[sensorid].get_alarm_min() else
                             'high'), self.sensors[sensorid].get_data())

                    # Make time for other web request
                    sleep(0.1)

                # Get the current average temperatures
                average_data = self.get_sensors(['average'])['sensors']

                # Websocket callback
                self.__send_message({
                    'type': 'sensor_gauge',
                    'data': average_data
                })

                # Update (remote) power switches
                for power_switch_id in self.power_switches:
                    # Update timer trigger if activated
                    self.power_switches[power_switch_id].timer()
                    # Update the current sensor.
                    self.power_switches[power_switch_id].update()
                    # Make time for other web request
                    sleep(0.1)

                # Websocket messages back
                self.get_uptime(socket=True)
                self.get_power_usage_water_flow(socket=True)
                self.get_environment(socket=True)
                self.get_audio_playing(socket=True)

                # Log system stats
                system_data = self.get_system_stats()
                self.collector.log_system_data(system_data)
                self.get_system_stats(socket=True)

                for webcamid in self.webcams:
                    self.webcams[webcamid].update()
                    sleep(0.1)

            except Exception, err:
                print err

            display_message = [
                '%s %s' % (
                    _('Uptime'),
                    terrariumUtils.format_uptime(system_data['uptime']),
                ),
                '%s %s %s %s' %
                (_('Load'), system_data['load']['load1'],
                 system_data['load']['load5'], system_data['load']['load15']),
                '%s %.2f%s' % (_('CPU Temp.'), system_data['temperature'],
                               self.get_temperature_indicator())
            ]

            for env_part in average_data:
                alarm_icon = '!' if average_data[env_part]['alarm'] else ''
                display_message.append(
                    '%s%s %.2f%s%s' %
                    (alarm_icon, _(env_part.replace('average_', '').title()),
                     average_data[env_part]['current'],
                     average_data[env_part]['indicator'], alarm_icon))

            self.notification.send_display(display_message)

            duration = (time.time() - starttime) + time_short
            if duration < terrariumEngine.LOOP_TIMEOUT:
                if error_counter > 0:
                    error_counter -= 1
                logger.info(
                    'Update done in %.5f seconds. Waiting for %.5f seconds for next update'
                    % (duration, terrariumEngine.LOOP_TIMEOUT - duration))
                time_short = 0
                sleep(terrariumEngine.LOOP_TIMEOUT -
                      duration)  # TODO: Config setting
            else:
                error_counter += 1
                if error_counter > 9:
                    logger.error(
                        'Updating is having problems keeping up. Could not update in 30 seconds for %s times!'
                        % error_counter)

                logger.warning(
                    'Updating took to much time. Needed %.5f seconds which is %.5f more then the limit %s'
                    % (duration, duration - terrariumEngine.LOOP_TIMEOUT,
                       terrariumEngine.LOOP_TIMEOUT))
                time_short = duration - terrariumEngine.LOOP_TIMEOUT
                if time_short > 12:
                    # More then 12 seconds to late.... probably never fast enough...
                    time_short = 0
Пример #2
0
  def __upgrade(self,to_version):
    # Set minimal version to 3.0.0
    current_version = 300
    table_upgrades = {'310' : ['ALTER TABLE system_data ADD COLUMN disk_total INTEGER(6)',
                               'ALTER TABLE system_data ADD COLUMN disk_used INTEGER(6)',
                               'ALTER TABLE system_data ADD COLUMN disk_free INTEGER(6)'],

                      '380' : ['DROP INDEX IF EXISTS sensor_data_type',
                               'CREATE INDEX IF NOT EXISTS sensor_data_avg ON sensor_data (type, timestamp ASC)',
                               'DROP INDEX IF EXISTS sensor_data_id',
                               'CREATE INDEX IF NOT EXISTS sensor_data_id ON sensor_data (id, timestamp ASC)',
                               'DROP INDEX IF EXISTS switch_data_id',
                               'CREATE INDEX IF NOT EXISTS switch_data_id ON switch_data (id, timestamp ASC)',
                               'DROP INDEX IF EXISTS door_data_id',
                               'CREATE INDEX IF NOT EXISTS door_data_id ON door_data (id, timestamp ASC)']}

    try:
      with open('.collector.update.{}.sql'.format('393'),'r') as sql_file:
        table_upgrades['393'] = [line.strip() for line in sql_file.readlines()]

      os.remove('.collector.update.{}.sql'.format('393'))
      logger.warning('There are {} sensors that have an updated ID and needs to be renamed in the database. This can take a lot of time! Please wait...'
                     .format(len(table_upgrades['393'])/2))

    except IOError as ex:
      # No updates... just ignore
      pass

    with self.db as db:
      cur = db.cursor()
      db_version = int(cur.execute('PRAGMA user_version').fetchall()[0][0])
      if db_version > current_version:
        current_version = db_version

    if current_version == to_version:
      logger.info('Collector database is up to date')
    elif current_version < to_version:
      logger.info('Collector database is out of date. Running updates from %s to %s' % (current_version,to_version))
      # Execute updates
      with self.db as db:
        cur = db.cursor()
        for update_version in table_upgrades:
          if current_version < int(update_version) <= to_version:
            # Execute all updates between the versions
            for sql_upgrade in table_upgrades[update_version]:
              try:
                cur.execute(sql_upgrade)
                logger.info('Collector database upgrade for version %s succeeded! %s' % (update_version,sql_upgrade))
              except Exception as ex:
                if 'duplicate column name' not in str(ex):
                  logger.error('Error updating collector database. Please contact support. Error message: %s' % (ex,))

            if '380' == update_version:
              self.__upgrade_to_380()

        db.commit()
        if int(to_version) % 10 == 0:
          logger.warning('Cleaning up disk space. This will take a couple of minutes depending on the database size and sd card disk speed.')
          filesize = os.path.getsize(terrariumCollector.DATABASE)
          speed = 2 # MBps
          duration = filesize / 1024.0 / 1024.0 / speed
          logger.warning('Current database is {} in size and with a speed of {}MBps it will take {} to complete'.format(terrariumUtils.format_filesize(filesize),speed,terrariumUtils.format_uptime(duration)))
          cur.execute('VACUUM')

        cur.execute('PRAGMA user_version = ' + str(to_version))
        logger.info('Updated collector database. Set version to: %s' % (to_version,))

      db.commit()