C# 需要使用内存/cpu效率在特定时间间隔内分析近实时数据的想法

C# 需要使用内存/cpu效率在特定时间间隔内分析近实时数据的想法,c#,math,real-time,.net-micro-framework,C#,Math,Real Time,.net Micro Framework,我有一些环境传感器,我想检测温度的突然变化,以及随时间变化的缓慢趋势。。。然而,我想根据内存中的参数来做大部分的数学运算,这些参数可能是这样的:(可能会改变) (注:参数中的项目在添加数据时实时计算) 5分钟(导数、最大值、最小值、平均值)+36个数据点,最新3小时 10分钟(导数、最大值、最小值、平均值)+0个数据点,计算基于5分钟样本 30分钟(导数、最大值、最小值、平均值)+0个数据点,计算基于5分钟样本 每小时(导数、最大值、最小值、平均值)+24个数据点,最新1天 每日(导数、最大值

我有一些环境传感器,我想检测温度的突然变化,以及随时间变化的缓慢趋势。。。然而,我想根据内存中的参数来做大部分的数学运算,这些参数可能是这样的:(可能会改变)

(注:参数中的项目在添加数据时实时计算)

  • 5分钟(导数、最大值、最小值、平均值)+36个数据点,最新3小时
  • 10分钟(导数、最大值、最小值、平均值)+0个数据点,计算基于5分钟样本
  • 30分钟(导数、最大值、最小值、平均值)+0个数据点,计算基于5分钟样本
  • 每小时(导数、最大值、最小值、平均值)+24个数据点,最新1天
  • 每日(导数、最大值、最小值、平均值)+当前月份的32个数据点
  • 过去一年每月(导数、最大值、最小值、平均值)+12个数据点
每个数据点都是一个双字节浮点。因此,每个传感器将消耗多达124个浮点数,加上24个计算变量。我希望在.NET嵌入式EDD设备允许的范围内支持尽可能多的传感器

因为我在这个项目中使用嵌入式设备,所以我的内存受到限制,IO和CPU的能力也受到限制

您将如何在.NET中实现这一点?到目前为止,我已经创建了两个结构,并将其称为“
TrackableFloat
”,其中插入一个值会导致旧的值从数组中删除,并进行重新计算

唯一能让这更有趣的是 比这更复杂,是吗 对于任何传感器,都不会返回报告 数据,那么该数据点需要 从所有后续文件中排除/忽略 实时计算

当所有操作都完成后,如果任何值:(导数、最大值、最小值、平均值)达到预定义的设置,则会触发.NET事件

我认为有人会认为这是一个有趣的问题,并希望听到他们将如何实现它

  • 你会使用类还是结构

  • 你将如何触发计算?(最有可能发生的事件)

  • 如何触发警报

  • 您将如何分层存储数据

  • 有没有这样的图书馆?(也许这应该是我的第一个问题)

  • 如何有效地计算导数

  • 这是我在这方面的第一次尝试,它没有完全达到规范要求,但是非常有效。我很想听听你的想法

    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;
                        }
                    }
                }
            }
        }
    }
    
    enum unittotracknum
    {
    分钟,
    五分钟,
    十分钟,
    十五分钟,
    小时,
    白天
    周,
    月,
    未知的
    }
    类可跟踪浮点
    {
    对象门=新对象();
    UnitToTrackNum trackingMode=UnitToTrackNum.unknown;
    int ValidFloats=0;
    浮动[]浮动轨道;
    公共可跟踪浮点(整数历史长度,UnitToTrackNum unitToTrack)
    {
    if(unitToTrack==UnitToTrackNum.unknown)
    抛出新的InvalidOperationException(“您不能有未知的跟踪时间度量。”);
    FloatsToTrack=新浮点[HistoryLength];
    foreach(FloatsToTrack中的变量i)
    {
    float[i]=float.MaxValue;
    }
    跟踪模式=unitToTrack;
    Min=float.MaxValue;
    Max=float.MinValue;
    总和=0;
    }
    公共无效添加(日期时间dt,浮点值)
    {
    int RoundedDTUnit=0;
    开关(跟踪模式)
    {
    案例UnitToTrackNum.分钟:
    {
    RoundedTunit=dt.分钟;
    打破
    }
    案例UnitToTrackNum.5分钟:
    {
    RoundedTunit=系统数学绝对值(dt.Minute/5);
    打破
    }
    案例UnitToTrackNum.TenMinute:
    {
    RoundedTunit=系统数学绝对值(dt.Minute/10);
    打破
    }
    案例单元到tracknum.fiftentenminute:
    {
    RoundedTunit=系统数学绝对值(dt.Minute/15);
    打破
    }
    案例UnitToTrackNum.小时:
    {
    RoundedTunit=dt.小时;
    打破
    }
    案例UnitToTrackNum.天:
    {
    RoundedTunit=dt.天;
    打破
    }
    案例UnitToTrackNum.周:
    {
    //RoundedDTUnit=System.Math.Abs();
    打破
    }
    案例UnitToTrackNum.月份:
    {
    RoundedTunit=dt.月;
    打破
    }
    案例UnitToTrackNum.unknown:
    {
    抛出新的InvalidOperationException(“您不能有未知的跟踪时间度量。”);
    }
    违约:
    打破
    }
    bool-DoRefreshMaxMin=false;
    if(FloatsToTrack.Length