Beispiel #1
0
    def get_hardware_state(self):
        data = None

        if self.__firmware is None:
            logger.error(
                'Sonoff device is not connected. Cannot read power switch state'
            )
            return terrariumPowerSwitch.OFF
        else:
            data = re.match(self.VALID_SOURCE, self.get_address())
            if data:
                data = data.groupdict()
                url = None

                if 'tasmota' == self.__firmware:
                    url = 'http://{}/cm?cmnd=Power'.format(data['host'])
                    if 'user' in data and 'password' in data:
                        url += '&user={}&password={}'.format(
                            data['user'], data['password'])

                elif 'espeasy' == self.__firmware:
                    url = 'http://{}/json'.format(data['host'])

                elif 'espurna' == self.__firmware:
                    if 'password' not in data:
                        # Just add dummy value...
                        data['password'] = '******'

                    url = 'http://{}/apis?apikey={}'.format(
                        data['host'], data['password'])

                state = terrariumUtils.get_remote_data(url)
                if state is None:
                    logger.warning(
                        'Error reading Sonoff \'{}\' power state. So retruning last known state: {}'
                        .format(self.get_name(), self.state))
                    return self.state

                if 'tasmota' == self.__firmware:
                    return terrariumPowerSwitch.ON if terrariumUtils.is_true(
                        state['POWER']) else terrariumPowerSwitch.OFF
                elif 'espeasy' == self.__firmware:
                    return terrariumPowerSwitch.ON if terrariumUtils.is_true(
                        state['POWER']) else terrariumPowerSwitch.OFF
                elif 'espurna' == self.__firmware:
                    return terrariumPowerSwitch.ON if terrariumUtils.is_true(
                        state['POWER']) else terrariumPowerSwitch.OFF

        return terrariumPowerSwitch.OFF
Beispiel #2
0
    def __template_variables(self, template):
        variables = {
            'lang':
            self.__terrariumEngine.config.get_language(),
            'title':
            self.__config['title'],
            'version':
            self.__config['version'],
            'page_title':
            _(template.replace('_', ' ').capitalize()),
            'temperature_indicator':
            self.__terrariumEngine.get_temperature_indicator(),
            'distance_indicator':
            self.__terrariumEngine.get_distance_indicator(),
            'volume_indicator':
            self.__terrariumEngine.get_volume_indicator(),
            'horizontal_graph_legend':
            1 if self.__terrariumEngine.get_horizontal_graph_legend() else 0,
            'translations':
            self.__translations,
            'device':
            self.__terrariumEngine.device,
            'notifications':
            self.__terrariumEngine.notification,
            'show_gauge_overview':
            terrariumUtils.is_true(self.__config['sensor_gauge_overview'])
        }

        if 'index' == template or 'profile' == template:
            variables['person_name'] = self.__terrariumEngine.get_profile_name(
            )
            variables[
                'person_image'] = self.__terrariumEngine.get_profile_image()

        return variables
Beispiel #3
0
  def _get_hardware_value(self):

    async def __get_hardware_state():
      data = []
      await self.device.update()

      plugs = [self.device] if len(self._address) == 1 else self.device.children
      for plug in plugs:
        data.append(plug.is_on)

      return data

    try:
      data = self.__state_cache.get_data(self._address[0])

      if data is None:
        toggle = asyncio.run_coroutine_threadsafe(__get_hardware_state(), self._async.async_loop)
        data = toggle.result()

        self.__state_cache.set_data(self._address[0],data,cache_timeout=20)

      return self.ON if len(data) >= self._device['switch'] and terrariumUtils.is_true(data[self._device['switch']]) else self.OFF
    except RuntimeError as err:
      logger.exception(err)
    except Exception as ex:
      logger.exception(ex)

    return None
Beispiel #4
0
    def _get_hardware_value(self):
        (device, nr) = self.device
        data = self._device_get(device, nr)
        if data is None:
            return None

        return self.ON if terrariumUtils.is_true(data) else self.OFF
Beispiel #5
0
  def __checker(self):
    logger.info('Start terrariumPI door checker for door \'%s\'' % self.get_name())
    while True:
      current_status = None
      if self.get_hardware_type() == 'gpio':
        current_status = terrariumDoor.OPEN if GPIO.input(terrariumUtils.to_BCM_port_number(self.get_address())) else terrariumDoor.CLOSED

      elif self.get_hardware_type() == 'remote' and (int(time.time()) - self.__last_check) >= terrariumDoor.REMOTE_TIMEOUT:
        current_status = None
        url_data = terrariumUtils.parse_url(self.get_address())
        if url_data is False:
          logger.error('Remote url \'%s\' for door \'%s\' is not a valid remote source url!' % (self.get_address(),self.get_name()))
        else:
          data = terrariumUtils.get_remote_data(self.get_address())
          if data is not None:
            current_status = terrariumDoor.OPEN if terrariumUtils.is_true(data) else terrariumDoor.CLOSED
          else:
            logger.warning('Remote door \'%s\' got error from remote source \'%s\'' % (self.get_name(),self.get_address()))

        self.__last_check = int(time.time())

      logger.debug('Current door \'%s\' status: %s' % (self.get_name(),current_status))
      if current_status != self.get_status():
        logger.info('Door \'%s\' changed from %s to %s' % (self.get_name(),self.get_status(), current_status))
        self.set_status(current_status)
        if self.callback is not None:
          self.callback(self.get_data())

      sleep(terrariumDoor.CHECKER_TIMEOUT)
Beispiel #6
0
  def _get_hardware_value(self):
#    self.device.reconnect_with_device()
    data = self.device.get_state(True)
    if data is None:
      return None

    return self.ON if terrariumUtils.is_true(data) else self.OFF
Beispiel #7
0
    def set_state(self, state, force=False):
        changed = False
        logger.debug(
            'Changing power switch \'{}\' of type \'{}\' at address \'{}\' from state \'{}\' to state \'{}\' (Forced:{})'
            .format(self.get_name(), self.get_type(), self.get_address(),
                    self.get_state(), state, force))

        if self.get_state() is not state or terrariumUtils.is_true(force):
            old_state = self.get_state()

            try:
                self.set_hardware_state(state, force)
                self.state = state
                logger.info(
                    'Changed power switch \'{}\' of type \'{}\' at address \'{}\' from state \'{}\' to state \'{}\' (Forced:{})'
                    .format(self.get_name(), self.get_type(),
                            self.get_address(), old_state, state, force))

            except Exception as ex:
                print(ex)
                logger.error(
                    'Failed changing power switch \'{}\' of type \'{}\' at address \'{}\' from state \'{}\' to state \'{}\' (Forced:{})'
                    .format(self.get_name(),
                            self.get_type(), self.get_address(),
                            self.get_state(), state, force))

            if (old_state is not None) or (old_state is None and state == 0):
                # This is due to a bug that will graph 0 watt usage in the graph after rebooting.
                # Fix is to add power and water usage in constructor
                changed = old_state != self.get_state()

        if changed and self.callback is not None:
            self.callback(self.get_data())

        return changed
            def wrapper(*a, **ka):

                if required or terrariumUtils.is_true(
                        self.__terrariumEngine.config.get_system()
                    ['always_authenticate']):
                    user, password = request.auth or (None, None)
                    ip = request.remote_addr if request.get_header(
                        'X-Real-Ip') is None else request.get_header(
                            'X-Real-Ip')
                    if user is None or not check(user, password):
                        err = HTTPError(401, text)
                        err.add_header('WWW-Authenticate',
                                       'Basic realm="%s"' % realm)
                        if user is not None or password is not None:
                            self.__terrariumEngine.notification.message(
                                'authentication_warning', {
                                    'ip': ip,
                                    'username': user,
                                    'password': password
                                }, [])
                            logger.warning(
                                'Incorrect login detected using username \'{}\' and password \'{}\' from ip {}'
                                .format(user, password, ip))
                        return err

                return func(*a, **ka)
  def update(self):
    if 'remote' in self.get_hardware_type():
      url_data = terrariumUtils.parse_url(self.get_address())
      if url_data is False:
        logger.error('Remote url \'%s\' for switch \'%s\' is not a valid remote source url!' % (self.get_address(),self.get_name()))
      else:
        try:
          data = requests.get(self.get_address(),auth=(url_data['username'],url_data['password']),timeout=3)

          if data.status_code == 200:
            data = data.json()
            json_path = url_data['fragment'].split('/') if 'fragment' in url_data and url_data['fragment'] is not None else []

            for item in json_path:
              # Dirty hack to process array data....
              try:
                item = int(item)
              except Exception, ex:
                item = str(item)

              data = data[item]

            if 'remote' == self.get_hardware_type():
              self.set_state(terrariumUtils.is_true(data))
            elif 'remote-dimmer' == self.get_hardware_type():
              self.set_state(int(data))

          else:
            logger.warning('Remote switch \'%s\' got error from remote source \'%s\':' % (self.get_name(),self.get_address(),data.status_code))
Beispiel #10
0
    def set_state(self, state, force=False):
        changed = False
        logger.debug(
            'Changing power switch \'{}\' of type \'{}\' at address \'{}\' from state \'{}\' to state \'{}\' (Forced:{})'
            .format(self.get_name(), self.get_type(), self.get_address(),
                    self.get_state(), state, force))

        if self.get_state() is not state or terrariumUtils.is_true(force):
            try:
                old_state = self.get_state()
                self.set_hardware_state(state, force)
                self.state = state
                changed = True

                logger.info(
                    'Changed power switch \'{}\' of type \'{}\' at address \'{}\' from state \'{}\' to state \'{}\' (Forced:{})'
                    .format(self.get_name(), self.get_type(),
                            self.get_address(), old_state, state, force))

            except Exception as ex:
                print(ex)
                logger.error(
                    'Failed changing power switch \'{}\' of type \'{}\' at address \'{}\' from state \'{}\' to state \'{}\' (Forced:{})'
                    .format(self.get_name(),
                            self.get_type(), self.get_address(),
                            self.get_state(), state, force))

        if changed and self.callback is not None:
            self.callback(self.get_data())

        return changed
Beispiel #11
0
  def set_state(self, new_state, force = False):
    if new_state is None or not (self.OFF <= new_state <= self.ON):
      logger.error(f'Illegal value for relay {self}: {new_state}')
      return False

    changed = False
    if self.state != new_state or terrariumUtils.is_true(force):
      old_state = self.state

      try:
        self.__set_hardware_value(new_state)
        #logger.info(f'Changed relay {self} from state \'{old_state}\' to state \'{new_state}\'')

      except Exception as ex:
        logger.error(f'Error changing state for relay {self} to {new_state} :{ex}')

      if (old_state is not None) or (old_state is None and new_state == 0):
        # This is due to a bug that will graph 0 watt usage in the graph after rebooting.
        # Fix is to add power and water usage in constructor
        changed = old_state != self.state

    if changed and self.callback is not None:
      self.callback(self.id, self.state)

    return changed
  def get_hardware_state(self):
    data = None

    if self.__firmware is None:
      if self.__retries < 5:
        self.__retries += 1
        logger.warning('Sonoff device is not connected while reading the state. Reconnect attempt: {}'.format(self.__retries))
        self.load_hardware()
        return self.get_hardware_state()
      else:
        logger.error('Sonoff device is not connected. Cannot read power switch state')
        return terrariumPowerSwitch.OFF

    data = re.match(self.VALID_SOURCE,self.get_address())
    if data:
      data = data.groupdict()
      url = None

      if 'tasmota' == self.__firmware:
        url = self.url

      elif 'espeasy' == self.__firmware:
        url = 'http://{}/json'.format(data['host'])

      elif 'espurna' == self.__firmware:
        if 'password' not in data:
          # Just add dummy value...
          data['password'] = '******'

        url = 'http://{}/apis?apikey={}'.format(data['host'],data['password'])

      state = terrariumUtils.get_remote_data(url)
      if state is None:
        logger.warning('Error reading Sonoff \'{}\' power state. So returning last known state: {}'.format(self.get_name(),self.state))
        return self.state

      if 'tasmota' == self.__firmware:
        for state_name, state_value in state.items():
          if state_name.startswith('POWER'):
            return terrariumPowerSwitch.ON if terrariumUtils.is_true(state_value) else terrariumPowerSwitch.OFF
      elif 'espeasy' == self.__firmware:
        return terrariumPowerSwitch.ON if terrariumUtils.is_true(state['POWER']) else terrariumPowerSwitch.OFF
      elif 'espurna' == self.__firmware:
        return terrariumPowerSwitch.ON if terrariumUtils.is_true(state['POWER']) else terrariumPowerSwitch.OFF

    return terrariumPowerSwitch.OFF
Beispiel #13
0
  def get_hardware_state(self):
    data = None
    url_data = terrariumUtils.parse_url(self.get_address())
    if url_data is False:
      logger.error('Remote url \'%s\' for switch \'%s\' is not a valid remote source url!' % (self.get_address(),self.get_name()))
    else:
      data = terrariumUtils.get_remote_data(self.get_address())

    return terrariumPowerSwitch.ON if terrariumUtils.is_true(data) else terrariumPowerSwitch.OFF
Beispiel #14
0
  def _get_data(self):
    result = self.device.read()
    if not terrariumUtils.is_true(result['valid']):
      return None

    data = {}
    data['temperature']  = result['temp_c']
    data['humidity']     = result['humidity']
    return data
Beispiel #15
0
            def wrapper(*a, **ka):
                if int(self.engine.settings['always_authenticate']) != -1 and (
                        required or terrariumUtils.is_true(
                            self.engine.settings['always_authenticate'])):
                    user, password = request.auth or (None, None)
                    ip = request.remote_addr if request.get_header(
                        'X-Real-Ip') is None else request.get_header(
                            'X-Real-Ip')
                    if user is None or not check(user, password):
                        err = HTTPError(401, text)
                        err.add_header('WWW-Authenticate',
                                       f'Basic realm="{realm}"')
                        if user is not None or password is not None:
                            self.engine.notification.message(
                                'authentication_error', {
                                    'ip': ip,
                                    'username': user,
                                    'password': password
                                }, [])
                            logger.warning(
                                f'Incorrect login detected using username \'{user}\' and password \'{password}\' from ip {ip}'
                            )
                        return err

                if request.method.lower() in ['get', 'head']:
                    self.__add_caching_headers(response, request.fullpath)

                    if request.url.lower().endswith(
                            '.html') or '/' == request.fullpath:
                        user, password = request.get_cookie(
                            'auth', secret=self.cookie_secret) or (None, None)
                        if check(user, password):
                            # Update the cookie timeout so that we are staying logged in as long as we are working on the interface
                            response.set_cookie('auth',
                                                request.get_cookie(
                                                    'auth',
                                                    secret=self.cookie_secret),
                                                secret=self.cookie_secret,
                                                **{
                                                    'max_age': 3600,
                                                    'path': '/'
                                                })

                elif request.method.lower() in ['post', 'put', 'delete']:
                    response.set_cookie('no-cache',
                                        '1',
                                        secret=None,
                                        **{
                                            'max_age': 90,
                                            'path': '/'
                                        })
                    response.set_header('Cache-Control', 'no-cache')

                return func(*a, **ka)
Beispiel #16
0
  def get_hardware_state(self):
    data = None
    try:
      port = pywemo.ouimeaux_device.probe_wemo(self.get_address())
      if port is not None:
        device = pywemo.discovery.device_from_description(terrariumPowerSwitchWeMo.URL.format(self.get_address(), port), None)
        data = device.get_state()

    except Exception as err:
      # Ignore for now
      print(err)

    return terrariumPowerSwitch.ON if terrariumUtils.is_true(data) else terrariumPowerSwitch.OFF
Beispiel #17
0
  def save_power_switches(self,data):
    update_ok = True
    for power_switch in self.get_power_switches():
      if 'exclude' not in power_switch or not terrariumUtils.is_true(power_switch['exclude']):
        self.__config.remove_section('switch' + power_switch['id'])

    for power_switch_id in data:
      update_ok = update_ok and self.save_power_switch(data[power_switch_id].get_data())

    if len(data) == 0:
      update_ok = update_ok and self.__save_config()

    return update_ok
Beispiel #18
0
  def save_sensors(self,data):
    update_ok = True
    for sensor in self.get_sensors():
      if 'exclude' not in sensor or not terrariumUtils.is_true(sensor['exclude']):
        self.__config.remove_section('sensor' + sensor['id'])

    for sensorid in data:
      update_ok = update_ok and self.save_sensor(data[sensorid].get_data())

    if len(data) == 0:
      update_ok = update_ok and self.__save_config()

    return update_ok
            def wrapper(*a, **ka):
                user, password = request.auth or (None, None)
                if required or terrariumUtils.is_true(
                        self.__terrariumEngine.config.get_system()
                    ['always_authenticate']):

                    if user is None or not check(user, password):
                        err = HTTPError(401, text)
                        err.add_header('WWW-Authenticate',
                                       'Basic realm="%s"' % realm)
                        return err

                return func(*a, **ka)
Beispiel #20
0
    def _get_hardware_value(self):
        cmd = f'{self.device} -n -g {self._address[0]}'
        data = terrariumUtils.get_script_data(cmd)
        if data is None:
            return None

        data = data.decode('utf-8').strip()
        relay_data = self.__STATUS_REGEX.search(data)
        if relay_data is not None and int(relay_data.group('relay_nr')) == int(
                self._address[0]):
            return self.ON if terrariumUtils.is_true(
                relay_data.group('status')) else self.OFF

        return None
Beispiel #21
0
    def _set_hardware_value(self, state):
        action = 1 if state == self.ON else 0
        url = f'{self.device}Power{self._address["nr"]}%20{action}'
        data = terrariumUtils.get_remote_data(url)

        if data is None:
            return False

        if 'POWER' in data:
            data = data['POWER']
        elif f'POWER{self._address["nr"]}' in data:
            data = data[f'POWER{self._address["nr"]}']

        return state == (self.ON if terrariumUtils.is_true(data) else self.OFF)
Beispiel #22
0
  def get_hardware_state(self):
    data = None

    try:
      tmpdata = self.__device.get_sys_data()
      for channel_data in tmpdata['all']['digest']['togglex']:
        if int(self.get_address()) == int(channel_data['channel']):
          data = channel_data['onoff']
          break

    except Exception as ex:
      print('Get hardware ex')
      print(ex)

    return terrariumPowerSwitch.ON if terrariumUtils.is_true(data) else terrariumPowerSwitch.OFF
Beispiel #23
0
    def _set_hardware_value(self, state):
        action = ('-o' if state == self.ON else '-f')
        cmd = f'{self.device} -n {action} {self._address[0]}'
        data = terrariumUtils.get_script_data(cmd)
        if data is None:
            return False

        data = data.decode('utf-8').strip()
        relay_data = self.__STATUS_REGEX.search(data)
        if relay_data is not None and int(relay_data.group('relay_nr')) == int(
                self._address[0]):
            return state == (self.ON if terrariumUtils.is_true(
                relay_data.group('status')) else self.OFF)

        return False
Beispiel #24
0
    def _get_hardware_value(self):
        EMAIL = terrariumUtils.decrypt(os.environ.get('MEROSS_EMAIL'))
        PASSWORD = terrariumUtils.decrypt(os.environ.get('MEROSS_PASSWORD'))

        if '' == EMAIL or '' == PASSWORD:
            logger.error('Meross cloud is not enabled.')
            return None

        data = self.__state_cache.get_data(self._device['device'])

        if data is None:
            return None

        return self.ON if len(
            data) >= self._device['switch'] and terrariumUtils.is_true(
                data[self._device['switch']]) else self.OFF
Beispiel #25
0
    def get_hardware_state(self):
        data = []

        async def __get_hardware_state(device, address):
            await device.update()
            strip = len(address) == 2
            if strip:
                data.append(device.plugs[int(address[1]) - 1].is_on)
            else:
                data.append(device.is_on)

        address = self.__get_address()
        try:
            asyncio.run(__get_hardware_state(self._device, address))
        except RuntimeError as err:
            return None

        return len(data) == 1 and terrariumUtils.is_true(data[0])
Beispiel #26
0
  def _get_hardware_value(self):
    cache_key = self.__relay_cache_key()
    data = self.__cache.get_data(cache_key)

    if data is None and not self.__cache.is_running(cache_key):
      self.__cache.set_running(cache_key)
      cmd = self.__CMD + [self._device['device'], self.__get_board_type(), 'all', 'status']

      data = subprocess.check_output(cmd).strip().decode('utf-8').strip()
      self.__cache.set_data(cache_key, data, cache_timeout = 20)
      self.__cache.clear_running(cache_key)

    if data is None:
      return None

    # Make string '0000' to list ['0','0','0','0']
    data = list(data)
    return self.ON if terrariumUtils.is_true(data[self._device['switch']-1]) else self.OFF
Beispiel #27
0
    def get_hardware_state(self):
        #data = None
        #print('Get hardware state cache data')
        data = self.__cache.get_data(self.__get_cache_key())
        #print(data)
        #print('IS running: {}' .format(self.__cache.is_running(self.__get_cache_key())))

        if data is None and not self.__cache.is_running(
                self.__get_cache_key()):
            self.__cache.set_running(self.__get_cache_key())

            cmd = [
                '/usr/bin/sudo', '/usr/bin/java', '-jar',
                'DenkoviRelayCommandLineTool/DenkoviRelayCommandLineTool.jar',
                self.__device,
                self._get_board_type(), 'all', 'status'
            ]
            logger.debug('Running get hardware state command {}'.format(cmd))
            #print('Running cmd: {}'.format(cmd))

            try:
                data = subprocess.check_output(cmd).strip().decode('utf-8')

                #print('Got data: *{}*'.format(data))
                self.__cache.set_data(self.__get_cache_key(), data)
            except Exception as err:
                # Ignore for now
                logger.error(
                    'Error getting hardware state for switch type {}, with error: {}'
                    .format(self.get_type(), err))

            self.__cache.clear_running(self.__get_cache_key())

        if data is None:
            return terrariumPowerSwitch.OFF

        address = int(self.get_address()) % self._get_relay_count()
        if address == 0:
            address = self._get_relay_count()

        #print('Final state data at address{} : {}'.format(address,data[address-1:address]))

        return terrariumPowerSwitch.ON if terrariumUtils.is_true(
            data[address - 1:address]) else terrariumPowerSwitch.OFF
Beispiel #28
0
    def _get_hardware_value(self):
        data = self.__cache.get_data(self.__cache_key)
        if data is None:
            # Cache is expired, so we update with new data
            # Get the overall state information
            url = f'{self.device}State'
            data = terrariumUtils.get_remote_data(url)

            if data is None:
                return None

            self.__cache.set_data(self.__cache_key, data, self._CACHE_TIMEOUT)

        if 'POWER' in data:
            data = data['POWER']
        elif f'POWER{self._address["nr"]}' in data:
            data = data[f'POWER{self._address["nr"]}']

        return self.ON if terrariumUtils.is_true(data) else self.OFF
Beispiel #29
0
  def _set_hardware_value(self, state):

    async def __set_hardware_state(state):
      await self.device.update()
      plug = self.device if len(self._address) == 1 else self.device.children[self._device['switch']]

      if state != 0.0:
        await plug.turn_on()
      else:
        await plug.turn_off()

      return state


    data = self.__state_cache.get_data(self._address[0])
    if data is not None and terrariumUtils.is_true(data[self._device['switch']]) == (state != 0.0):
      return True

    toggle = asyncio.run_coroutine_threadsafe(__set_hardware_state(state), self._async.async_loop)
    data = toggle.result()
    return data == state
Beispiel #30
0
    def _get_hardware_value(self):
        data = self.__cache.get_data(self.__cache_key)
        if data is None:
            # Cache is expired, so we update with new data
            # Get the overall state information
            if not self.__connect():
                raise terrariumRelayUpdateException(
                    f'Failed updating relay {self}. Unable to login')

            data = self.device.getstatus()

            if data is None:
                return None

            self.__cache.set_data(self.__cache_key, data, self._CACHE_TIMEOUT)

        address = self._address
        status = self.ON if terrariumUtils.is_true(
            data['sockets'][address['nr'] - 1]) else self.OFF
        self.__logout()

        return status