2011-01-27 6 views
2

У меня есть некоторые датчики окружающей среды, и я хочу обнаружить внезапные изменения температуры и медленные тенденции с течением времени ... однако я бы хотел сделать большинство в математике, основанной на том, что в памяти с параметрами, которые могут выглядеть следующим образом: (возможны изменения)Идеи, необходимые для анализа данных в режиме реального времени с определенными интервалами с эффективностью памяти/процессора

(примечание: Элементы скобок вычисляются в режиме реального времени по мере добавления данных)

  • 5 минут (производное , max, min, avg) + 36 точек передачи данных для большинства текущих 3 часов
  • 10 минут (производный, макс., мин., сред.) + 0 точки данных, известково основана на 5мин образце
  • 30 мин (производная, макс, мин, ср) + 0 точки данных, известково основана на 5 мин образце
  • Ежечасно (производная, макс, мин, ср) + 24 точек данные для большинства текущих 1 дня
  • Daily (производная, макс, мин, ср) + 32 точки данных для большинства текущего месяца
  • Ежемесячно (производная, макс, мин, средны) + 12 точки данных за прошедший год

Каждый datapoint представляет собой двухбайтный поплавок. Таким образом, каждый датчик будет потреблять до 124 Floats, плюс 24 рассчитанных переменных. Я бы хотел поддерживать столько сенсоров, сколько разрешит устройство .NET embededd.

Поскольку я использую встроенное устройство для этого проекта, моя память ограничена, а также моя мощность ввода-вывода и процессора.

Как бы вы реализовали это в .NET? До сих пор я создал пару структур и назвал его «TrackableFloat», где вставка значения приводит к тому, что старый из них выпадает из массива и выполняется пересчет.

Единственное, что делает это более сложнее, чем это было бы, что для любого датчика не сообщает данных, то, что DataPoint должен быть исключен/проигнорировано из все последующего calulations реального времени.

Когда все сказано и сделано, если любое из значений: (производное, не более, не менее, в среднем) достигают заранее определенные настройки, то срабатывает событие .NET

Я думаю, что кто-то там будет подумайте, что это интересная проблема, и хотелось бы услышать, как они подходят к ее внедрению.

  1. Вы бы использовали класс или конструкцию?

  2. Как бы вы инициировали расчеты? (Вероятнее всего, события)

  3. Как срабатывать оповещения?

  4. Как бы сохранить данные в своих строках?

  5. Есть ли библиотека, которая уже делает что-то вроде этого? (должно быть это должен быть мой первый вопрос)

  6. Как Вы бы эффективно вычислить производное предприятие?

Вот моя первая трещина на этом, и она не полностью ударила по спецификации, но очень эффективна. Было бы интересно услышать ваши мысли.

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; 
        } 
       } 
      } 
     } 
    } 
} 
+0

Какой формат этих двух байтовых поплавков? Вы выполняете с ними вычисления или конвертируете в обычные поплавки? Какой тип процессора это? – phkahler

ответ

1

Вы должны рассмотреть глядя на CEP библиотеку как Nesper.

+0

Я могу только L-GPL ... GPL2 - это не гонка, так как я внедряю несовместимый лицензионный код от других поставщиков. – LamonteCristo

+0

Я обнаружил, что кто-то может разместить код GPL2, и я могу ссылаться на него как на веб-службу, не влияя на другое приложение – LamonteCristo