Esempio n. 1
0
        public RulesEvaluationResult Evaluate(RuleApiModel rule, RawMessage message)
        {
            var result = new RulesEvaluationResult();

            if (GroupContainsDevice(message.DeviceId, rule.GroupId))
            {
                logger.Debug($"Evaluating rule {rule.Description} for device {message.DeviceId} with {rule.Conditions.Count()} conditions", () => { });

                var descriptions = new List <string>();
                foreach (var c in rule.Conditions)
                {
                    var eval = EvaluateCondition(c, message);
                    // perf: all conditions must match, break as soon as one doesn't
                    if (!eval.Match)
                    {
                        return(result);
                    }
                    descriptions.Add(eval.Message);
                }

                result.Match   = true;
                result.Message = string.Join("; ", descriptions);
            }
            else
            {
                logger.Debug($"Skipping rule {rule.Description} because device {message.DeviceId} doesn't belong to group {rule.GroupId}", () => { });
            }

            return(result);
        }
Esempio n. 2
0
        private RulesEvaluationResult EvaluateCondition(
            ConditionApiModel condition,
            RawMessage message)
        {
            var r = new RulesEvaluationResult();

            var    field = condition.Field;
            object value;

            if (!message.PayloadData.TryGetValue(field, out value))
            {
                logger.Debug($"Message payload doesn't contain field {field}", () => { });
                return(r);
            }

            OperatorLogic logic;

            if (!OperatorLogicLookup.TryGetValue(condition.Operator.ToLowerInvariant(), out logic))
            {
                logger.Error("Unknown operator", () => new { condition });
                return(r);
            }

            switch (Type.GetTypeCode(value.GetType()))
            {
            case TypeCode.SByte:
            case TypeCode.Byte:
            case TypeCode.Int16:
            case TypeCode.UInt16:
            case TypeCode.Int32:
            case TypeCode.UInt32:
            case TypeCode.Int64:
            case TypeCode.UInt64:
            case TypeCode.Single:
            case TypeCode.Double:
            case TypeCode.Decimal:
            {
                var actualValue = Convert.ToDouble(value);
                var threshold   = Convert.ToDouble(condition.Value);

                logger.Debug($"Field {field}, Value {actualValue}, Operator {condition.Operator}, Threshold {threshold}", () => { });
                if (logic.DoubleTestFunc(actualValue, threshold))
                {
                    r.Match   = true;
                    r.Message = string.Format(logic.Message, field, actualValue, threshold);
                }
            }
            break;

            case TypeCode.String:
            {
                var actualValue = value.ToString();
                var threshold   = condition.Value;

                logger.Debug($"Field {field}, Value '{actualValue}', Operator {condition.Operator}, Threshold '{threshold}'", () => { });
                if (logic.StringTestFunc(actualValue, threshold))
                {
                    r.Match   = true;
                    r.Message = string.Format(logic.Message, field, actualValue, threshold);
                }
            }
            break;

            default:
                logger.Error($"Unknown type for `{field}` value sent by device {message.DeviceId}", () => { });
                break;
            }

            return(r);
        }