def ValidateMessage(self, message):
        """Validates a telemetry message.

    Adds all validation errors for the message to a list of all errors
    discovered by this validator."""

        t = telemetry.Telemetry(message)
        entity_name = t.attributes[DEVICE_ID]

        if entity_name not in self.entities:
            self.AddError(
                telemetry_error.TelemetryError(entity_name, None,
                                               "Unknown entity"))
            message.ack()
            return

        if entity_name in self.validated_entities:
            # Already validated telemetry for this entity,
            # so the message can be skipped.
            return
        self.validated_entities[entity_name] = True

        entity = self.entities[entity_name]
        for point_name, point_config in entity[TRANSLATION].items():
            if point_name not in t.points.keys():
                self.AddError(
                    telemetry_error.TelemetryError(entity_name, point_name,
                                                   "Missing point"))
                continue

            point = t.points[point_name]
            pv = point.present_value
            if pv is None:
                self.AddError(
                    telemetry_error.TelemetryError(entity_name, point_name,
                                                   "Missing present value"))
                continue

            has_states = STATES in point_config
            has_units = UNITS in point_config

            if has_states:
                states = point_config[STATES]
                if pv not in states.values():
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, point_name,
                            "Invalid state: {}".format(pv)))
                    continue

            if has_units and not self.ValueIsNumeric(pv):
                self.AddError(
                    telemetry_error.TelemetryError(
                        entity_name, point_name,
                        "Invalid number: {}".format(pv)))

        message.ack()
        self.CallbackIfCompleted()
Esempio n. 2
0
  def testTelemetryValidatorGetErrorsReturnsAllErrors(self):
    validator = telemetry_validator.TelemetryValidator(_ENTITIES_1, 1,
                                                       _NULL_CALLBACK)
    error_one = telemetry_error.TelemetryError(_ENTITY_NAME_1, _POINT_NAME_1,
                                               'Test error 1')
    error_two = telemetry_error.TelemetryError(_ENTITY_NAME_2, _POINT_NAME_2,
                                               'Test error 2')

    validator.AddError(error_one)
    validator.AddError(error_two)
    errors = validator.GetErrors()

    self.assertIn(error_one, errors)
    self.assertIn(error_two, errors)
    self.assertLen(errors, 2)
Esempio n. 3
0
    def testTelemetryValidatorDetectsMultipleErrorsInMessage(self):
        validator = telemetry_validator.TelemetryValidator(
            _ENTITIES_1, 1, _NULL_CALLBACK)

        validator.ValidateMessage(_MESSAGE_MULTIPLE_ERRORS)

        error_one = telemetry_error.TelemetryError(
            _ENTITY_NAME_1, _POINT_NAME_1, 'Invalid number: BAD_NUMBER')
        error_two = telemetry_error.TelemetryError(_ENTITY_NAME_1,
                                                   _POINT_NAME_2,
                                                   'Missing point')
        errors = validator.GetErrors()
        self.assertIn(error_one, errors)
        self.assertIn(error_two, errors)
        self.assertEqual(len(errors), 2)
Esempio n. 4
0
  def testTelemetryValidatorDetectsUnmappedState(self):
    validator = telemetry_validator.TelemetryValidator(_ENTITIES_2, 1,
                                                       _NULL_CALLBACK)

    validator.ValidateMessage(_MESSAGE_INVALID_STATE)

    error1 = telemetry_error.TelemetryError(
        _ENTITY_NAME_2, _POINT_NAME_3, 'Unmapped state in telemetry message'
        ': BAD_STATE')
    error2 = telemetry_error.TelemetryError(
        _ENTITY_NAME_2, _POINT_NAME_4, 'Unmapped state in telemetry message: 3')

    errors = validator.GetErrors()
    self.assertIn(error1, errors)
    self.assertIn(error2, errors)
    self.assertLen(errors, 2)
Esempio n. 5
0
    def testTelemetryValidatorDetectsMultipleErrorsInMessage(self):
        validator = telemetry_validator.TelemetryValidator(
            _ENTITIES_1, 1, _NULL_CALLBACK)

        validator.ValidateMessage(_MESSAGE_MULTIPLE_ERRORS)

        error_one = telemetry_error.TelemetryError(
            _ENTITY_NAME_1, _POINT_NAME_1, 'Missing number in telemetry '
            'message: None')
        error_two = telemetry_error.TelemetryError(
            _ENTITY_NAME_1, _POINT_NAME_2, 'Field missing from telemetry '
            'message')

        errors = validator.GetErrors()
        self.assertIn(error_one, errors)
        self.assertIn(error_two, errors)
        self.assertLen(errors, 2)
Esempio n. 6
0
  def testTelemetryValidatorDetectsInvalidState(self):
    validator = telemetry_validator.TelemetryValidator(_ENTITIES_2, 1,
                                                       _NULL_CALLBACK)

    validator.ValidateMessage(_MESSAGE_INVALID_STATE)

    error1 = telemetry_error.TelemetryError(
        _ENTITY_NAME_2, _POINT_NAME_3, 'Missing state in telemetry message'
        ': None')
    error2 = telemetry_error.TelemetryError(
        _ENTITY_NAME_2, _POINT_NAME_4, 'Missing state in telemetry message'
        ': None')

    errors = validator.GetErrors()
    self.assertIn(error1, errors)
    self.assertIn(error2, errors)
    self.assertEqual(len(errors), 2)
Esempio n. 7
0
    def testTelemetryValidatorDetectsUnknownEntity(self):
        validator = telemetry_validator.TelemetryValidator({}, 1,
                                                           _NULL_CALLBACK)

        validator.ValidateMessage(_MESSAGE_GOOD)

        error = telemetry_error.TelemetryError(_ENTITY_NAME_1, None,
                                               'Unknown entity')
        errors = validator.GetErrors()
        self.assertIn(error, errors)
        self.assertEqual(len(errors), 1)
Esempio n. 8
0
    def testTelemetryValidatorDetectsBooleanAsInvalidNumber(self):
        validator = telemetry_validator.TelemetryValidator(
            _ENTITIES_1, 1, _NULL_CALLBACK)

        validator.ValidateMessage(_MESSAGE_INVALID_NUMBER_BOOLEAN)

        error = telemetry_error.TelemetryError(_ENTITY_NAME_1, _POINT_NAME_1,
                                               'Invalid number: False')
        errors = validator.GetErrors()
        self.assertIn(error, errors)
        self.assertEqual(len(errors), 1)
Esempio n. 9
0
    def testTelemetryValidatorDetectsInvalidState(self):
        validator = telemetry_validator.TelemetryValidator(
            _ENTITIES_2, 1, _NULL_CALLBACK)

        validator.ValidateMessage(_MESSAGE_INVALID_STATE)

        error = telemetry_error.TelemetryError(_ENTITY_NAME_2, _POINT_NAME_3,
                                               'Invalid state: BAD_STATE')
        errors = validator.GetErrors()
        self.assertIn(error, errors)
        self.assertEqual(len(errors), 1)
Esempio n. 10
0
    def testTelemetryValidatorDetectsMissingPresentValue(self):
        validator = telemetry_validator.TelemetryValidator(
            _ENTITIES_1, 1, _NULL_CALLBACK)

        validator.ValidateMessage(_MESSAGE_MISSING_PRESENT_VALUE)

        error = telemetry_error.TelemetryError(_ENTITY_NAME_1, _POINT_NAME_1,
                                               'Missing present value')
        errors = validator.GetErrors()
        self.assertIn(error, errors)
        self.assertEqual(len(errors), 1)
Esempio n. 11
0
  def testTelemetryValidatorDetectsMissingPoint(self):
    validator = telemetry_validator.TelemetryValidator(_ENTITIES_1, 1,
                                                       _NULL_CALLBACK)

    validator.ValidateMessage(_MESSAGE_MISSING_POINT)

    error = telemetry_error.TelemetryError(
        _ENTITY_NAME_1, _POINT_NAME_2, 'Field missing from '
        'telemetry message')
    errors = validator.GetErrors()
    self.assertIn(error, errors)
    self.assertLen(errors, 1)
Esempio n. 12
0
  def testTelemetryValidatorDetectsNoneValue(self):
    validator = telemetry_validator.TelemetryValidator(_ENTITIES_1, 1,
                                                       _NULL_CALLBACK)

    validator.ValidateMessage(_MESSAGE_INVALID_NUMBER)

    error = telemetry_error.TelemetryError(
        _ENTITY_NAME_1, _POINT_NAME_1, 'Missing number in telemetry message'
        ': None')

    errors = validator.GetErrors()
    self.assertIn(error, errors)
    self.assertEqual(len(errors), 1)
Esempio n. 13
0
  def testTelemetryValidatorDetectsStringAsInvalidNumber(self):
    validator = telemetry_validator.TelemetryValidator(_ENTITIES_1, 1,
                                                       _NULL_CALLBACK)

    validator.ValidateMessage(_MESSAGE_INVALID_NUMBER)

    error = telemetry_error.TelemetryError(
        _ENTITY_NAME_1, _POINT_NAME_1, 'Invalid number in telemetry message'
        ': BAD_NUMBER')

    errors = validator.GetErrors()
    self.assertIn(error, errors)
    self.assertLen(errors, 1)
    def testTelemetryValidatorDetectsBooleanAsInvalidNumber(self):
        validator = telemetry_validator.TelemetryValidator(
            _ENTITIES_1, 1, _NullCallback)

        validator.ValidateMessage(_MESSAGE_INVALID_NUMBER_BOOLEAN)

        error = telemetry_error.TelemetryError(
            _ENTITY_NAME_1, _POINT_NAME_1,
            'Invalid number in telemetry message'
            ': false')

        errors = validator.GetErrors()
        self.assertIn(error, errors)
        self.assertLen(errors, 1)
    def testTelemetryValidatorDetectsMissingPresentValue(self):
        validator = telemetry_validator.TelemetryValidator(
            _ENTITIES_1, 1, _NullCallback)

        validator.ValidateMessage(_MESSAGE_MISSING_PRESENT_VALUE)

        error = telemetry_error.TelemetryError(
            _ENTITY_NAME_1, _POINT_NAME_1,
            'Missing number in telemetry message'
            ': None')

        errors = validator.GetErrors()
        self.assertIn(error, errors)
        self.assertLen(errors, 1)
    def ValidateMessage(self, message):
        """Validates a telemetry message.

    Args:
      message: the telemetry message to validate.

    Adds all validation errors for the message to a list of all errors
    discovered by this validator.
    """

        tele = telemetry.Telemetry(message)
        entity_name = tele.attributes[DEVICE_ID]

        # Telemetry message received for an entity not in building config
        if entity_name not in self.entities_with_translation.keys():
            # TODO(charbull): refactor warning class
            self.AddWarning(
                telemetry_warning.TelemetryWarning(
                    entity_name, None,
                    'Telemetry message received for an entity not '
                    'in building config'))
            message.ack()
            return

        if entity_name in self.validated_entities:
            # Already validated telemetry for this entity,
            # so the message can be skipped.
            message.ack()
            return
        self.validated_entities[entity_name] = True

        entity = self.entities_with_translation[entity_name]

        print(f'Validating telemetry message for entity: {entity_name}')
        point_full_paths = {
            f'points.{key}.present_value': key
            for key in tele.points
        }
        for field_translation in entity.translation.values():
            if isinstance(field_translation, ft_lib.UndefinedField):
                continue
            if field_translation.raw_field_name not in point_full_paths:
                if not tele.is_partial:
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            'Field missing from telemetry message'))
                continue
            point = tele.points[point_full_paths[
                field_translation.raw_field_name]]
            pv = point.present_value
            if pv is None:
                if isinstance(field_translation, ft_lib.MultiStateValue):
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            f'Missing state in telemetry message: {pv}'))
                elif isinstance(field_translation, ft_lib.DimensionalValue):
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            f'Missing number in telemetry message: {pv}'))
                else:
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            'Present value missing from telemetry message'))
                continue

            if isinstance(field_translation, ft_lib.MultiStateValue):
                if pv not in field_translation.raw_values:
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            f'Invalid state in telemetry message: {pv}'))

                    continue

            if isinstance(
                    field_translation,
                    ft_lib.DimensionalValue) and not self.ValueIsNumeric(pv):
                self.AddError(
                    telemetry_error.TelemetryError(
                        entity_name, field_translation.raw_field_name,
                        f'Invalid number in telemetry message: {pv}'))

        message.ack()
        self.CallbackIfCompleted()
Esempio n. 17
0
    def ValidateMessage(self, message):
        """Validates a telemetry message.

    Adds all validation errors for the message to a list of all errors
    discovered by this validator."""

        tele = telemetry.Telemetry(message)
        entity_name = tele.attributes[DEVICE_ID]

        # Telemetry message received for an entity not in building config
        if entity_name not in self.entities_with_translation.keys():
            #TODO(charbull): refactor warning class
            self.AddWarning(
                telemetry_warning.TelemetryWarning(
                    entity_name, None,
                    'Telemetry message received for an entity not '
                    'in building config'))
            message.ack()
            return

        if entity_name in self.validated_entities:
            # Already validated telemetry for this entity,
            # so the message can be skipped.
            message.ack()
            return
        self.validated_entities[entity_name] = True

        entity = self.entities_with_translation[entity_name]

        print(
            'Validating telemetry message for entity: {0}'.format(entity_name))

        for field_translation in entity.translation.values():
            if field_translation.raw_field_name not in tele.points.keys():
                if not tele.is_partial:
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            'Field missing from telemetry message'))
                continue

            point = tele.points[field_translation.raw_field_name]
            pv = point.present_value
            if pv is None:
                if field_translation.states:
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            'Missing state in telemetry '
                            'message: {}'.format(pv)))
                elif field_translation.units:
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            'Missing number in telemetry '
                            'message: {}'.format(pv)))
                else:
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            'Present value missing from '
                            'telemetry message'))
                continue

            if field_translation.states:
                if pv not in field_translation.states.values():
                    self.AddError(
                        telemetry_error.TelemetryError(
                            entity_name, field_translation.raw_field_name,
                            'Invalid state in telemetry message: {}'.format(
                                pv)))

                    continue

            if field_translation.units and not self.ValueIsNumeric(pv):
                self.AddError(
                    telemetry_error.TelemetryError(
                        entity_name, field_translation.raw_field_name,
                        'Invalid number in telemetry message: {}'.format(pv)))

        message.ack()
        self.CallbackIfCompleted()