Des idées voulaient pour analyser des données quasi temps réel sur des intervalles de spécifiques avec efficacité mémoire / cpu

StackOverflow https://stackoverflow.com/questions/4813556

Question

J'ai des capteurs environnementaux et je veux détecter les changements brusques de température, et les tendances lentes au fil du temps ... mais je voudrais faire la plupart des mathématiques basée sur ce qui est en mémoire avec des paramètres qui peuvent ressembler à ceci: (sous réserve de modifications)

(Remarque: Les éléments en parens sont calculés en temps réel données sont ajoutées)

  • 5 minute (dérivé, max, min, moyenne) + 36 pour la plupart des points de données actuelles 3 heures
  • 10 minutes (dérivé, max, min, moyenne) + 0 points de données, calc est basé sur l'échantillon 5min
  • 30 minute (dérivé, max, min, moyenne) + 0 points de données, calc est basé sur un échantillon de 5 min
  • horaire (dérivé, max, min, moyenne) + 24 points de données pour la plupart un jour actuel
  • Daily (dérivé, max, min, moyenne) + 32 points de données pour la plupart mois en cours
  • mensuel (dérivé, max, min, moyenne) + 12 points de données pour la dernière année

Chaque point de données est un flotteur à deux octets. Ainsi, chaque capteur consomme jusqu'à 124 Flotteurs, ainsi que les 24 variables calculées. Je voudrais soutenir autant de capteurs que le dispositif de embededd .NET permettra.

Depuis que je suis en utilisant un appareil embarqué pour ce projet, ma mémoire est limitée et est donc mon pouvoir IO et CPU.

Comment iriez-vous sur l'implémentation de cela dans .NET? Jusqu'à présent, j'ai créé quelques struct et l'a appelé un « TrackableFloat » où l'insertion d'une valeur provoque l'ancienne pour déposer le tableau et un recalcul est fait.

La seule chose qui rend ce plus compliqué que ce serait, est que pour tout capteur ne pas rapport données, alors que des points de données doit être exclus / ignoré de tous suite calulations en temps réel.

Quand tout est dit et fait, si l'une des valeurs suivantes: (dérivé, max, min, avg) atteignent un paramètre prédéfini, puis un événement se déclenche .NET

Je pense que quelqu'un là-bas penseront que cela est un problème intéressant, et je serais ravi d'entendre leur façon d'aborder sa mise en œuvre.

  1. Souhaitez-vous utiliser une classe ou un struct?

  2. Comment voulez-vous déclencher les calculs? (Les événements le plus probable)

  3. Comment les alertes déclenchée?

  4. Comment voulez-vous stocker les données, dans les niveaux?

  5. Y at-il une bibliothèque qui fait déjà quelque chose comme ça? (Peut-être que cela devrait être ma première question)

  6. Comment qualifieriez-vous de calculer efficacement la dérivée?

Voici ma première fissure à cela, et il n'a pas complètement atteint les spécifications, mais il est très efficace. Serait intéressé à entendre vos pensées.

enum UnitToTrackEnum
{
    Minute,
    FiveMinute,
    TenMinute,
    FifteenMinute,
    Hour,
    Day,
    Week,
    Month,
    unknown
}
class TrackableFloat
{
    object Gate = new object();

    UnitToTrackEnum trackingMode = UnitToTrackEnum.unknown;
    int ValidFloats = 0;
    float[] FloatsToTrack;

    public TrackableFloat(int HistoryLength, UnitToTrackEnum unitToTrack)
    {
        if (unitToTrack == UnitToTrackEnum.unknown)
            throw new InvalidOperationException("You must not have an unknown measure of time to track.");

        FloatsToTrack = new float[HistoryLength];

        foreach (var i in FloatsToTrack)
        {
            float[i] = float.MaxValue;
        }


        trackingMode = unitToTrack;

        Min = float.MaxValue;
        Max = float.MinValue;
        Sum = 0;
    }
    public void Add(DateTime dt, float value)
    {
        int RoundedDTUnit = 0;

        switch (trackingMode)
        {
            case UnitToTrackEnum.Minute:
                {
                    RoundedDTUnit = dt.Minute;
                    break;
                }
            case UnitToTrackEnum.FiveMinute:
                {
                    RoundedDTUnit = System.Math.Abs(dt.Minute / 5);
                    break;
                }
            case UnitToTrackEnum.TenMinute:
                {
                    RoundedDTUnit = System.Math.Abs(dt.Minute / 10);
                    break;
                }
            case UnitToTrackEnum.FifteenMinute:
                {
                    RoundedDTUnit = System.Math.Abs(dt.Minute / 15);
                    break;
                }
            case UnitToTrackEnum.Hour:
                {
                    RoundedDTUnit = dt.Hour;
                    break;
                }
            case UnitToTrackEnum.Day:
                {
                    RoundedDTUnit = dt.Day;
                    break;
                }
            case UnitToTrackEnum.Week:
                {
                    //RoundedDTUnit = System.Math.Abs( );
                    break;
                }
            case UnitToTrackEnum.Month:
                {
                    RoundedDTUnit = dt.Month;
                    break;
                }
            case UnitToTrackEnum.unknown:
                {
                    throw new InvalidOperationException("You must not have an unknown measure of time to track.");
                }
            default:
                break;
        }


        bool DoRefreshMaxMin = false;
        if (FloatsToTrack.Length < RoundedDTUnit)
        {
            if (value == float.MaxValue || value == float.MinValue)
            {
                // If invalid data...
                lock (Gate)
                {
                    // Get rid of old data...
                    var OldValue = FloatsToTrack[RoundedDTUnit];
                    if (OldValue != float.MaxValue || OldValue != float.MinValue)
                    {
                        Sum -= OldValue;
                        ValidFloats--;

                        if (OldValue == Max || OldValue == Min)
                            DoRefreshMaxMin = true;
                    }

                    // Save new data
                    FloatsToTrack[RoundedDTUnit] = value;
                }
            }
            else
            {
                lock (Gate)
                {
                    // Get rid of old data...
                    var OldValue = FloatsToTrack[RoundedDTUnit];
                    if (OldValue != float.MaxValue || OldValue != float.MinValue)
                    {
                        Sum -= OldValue;
                        ValidFloats--;
                    }

                    // Save new data
                    FloatsToTrack[RoundedDTUnit] = value;
                    Sum += value;
                    ValidFloats++;

                    if (value < Min)
                        Min = value;

                    if (value > Max)
                        Max = value;

                    if (OldValue == Max || OldValue == Min)
                        DoRefreshMaxMin = true;
                }
            }

            // Function is placed here to avoid a deadlock
            if (DoRefreshMaxMin == true)
                RefreshMaxMin();
        }
        else
        {
            throw new IndexOutOfRangeException("Index " + RoundedDTUnit + " is out of range for tracking mode: " + trackingMode.ToString());
        }
    }

    public float Sum { get; set; }
    public float Average
    {
        get
        {
            if (ValidFloats > 0)
                return Sum / ValidFloats;
            else
                return float.MaxValue;
        }
    }
    public float Min { get; set; }
    public float Max { get; set; }
    public float Derivative { get; set; }

    public void RefreshCounters()
    {
        lock (Gate)
        {
            float sum = 0;
            ValidFloats = 0;

            Min = float.MaxValue;
            Max = float.MinValue;

            foreach (var i in FloatsToTrack)
            {
                if (i != float.MaxValue || i != float.MinValue)
                {
                    if (Min == float.MaxValue)
                    {
                        Min = i;
                        Max = i;
                    }

                    sum += i;
                    ValidFloats++;

                    if (i < Min)
                        Min = i;

                    if (i > Max)
                        Max = i;
                }
            }
            Sum = sum;
        }
    }
    public void RefreshMaxMin()
    {
        if (ValidFloats > 0)
        {
            Min = float.MaxValue;
            Max = float.MinValue;

            lock (Gate)
            {
                foreach (var i in FloatsToTrack)
                {
                    if (i != float.MaxValue || i != float.MinValue)
                    {
                        if (i < Min)
                            Min = i;

                        if (i > Max)
                            Max = i;
                    }
                }
            }
        }
    }
}
Était-ce utile?

La solution

Vous devriez envisager de regarder un CEP bibliothèque comme Nesper .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top