Ejemplo n.º 1
0
        private HashSet <Tuple <int, SeriesID, DateTime> > FindExistingTrendingPoints(MeterDataSet meterDataSet, Historian historian)
        {
            HashSet <Tuple <int, SeriesID, DateTime> > existingTrendingPoints = new HashSet <Tuple <int, SeriesID, DateTime> >();
            Dictionary <Channel, List <DataGroup> >    trendingDataGroups     = meterDataSet.GetResource <TrendingGroupsResource>().TrendingGroups;

            IEnumerable <IGrouping <Tuple <DateTime, DateTime>, TrendingRange> > channelGroups = trendingDataGroups
                                                                                                 .SelectMany(kvp => kvp.Value.Select(dataGroup => new TrendingRange(kvp.Key, dataGroup)))
                                                                                                 .GroupBy(trendingRange => Tuple.Create(trendingRange.StartTime, trendingRange.EndTime));

            foreach (IGrouping <Tuple <DateTime, DateTime>, TrendingRange> channelGroup in channelGroups)
            {
                DateTime          startTime = channelGroup.Key.Item1;
                DateTime          stopTime  = channelGroup.Key.Item2;
                IEnumerable <int> channels  = channelGroup.Select(trendingRange => trendingRange.Channel.ID);
                IEnumerable <TrendingDataPoint> trendingPoints = null;

                try
                {
                    trendingPoints = historian.Read(channels, startTime, stopTime);

                    foreach (TrendingDataPoint trendingPoint in trendingPoints)
                    {
                        existingTrendingPoints.Add(GetKey(trendingPoint));
                    }
                }
                finally
                {
                    (trendingPoints as IDisposable)?.Dispose();
                }
            }

            return(existingTrendingPoints);
        }
Ejemplo n.º 2
0
        private string GetTHDJsonString(IGrouping <int, DisturbanceData> assetGroup, DateTime startDate, DateTime endDate)
        {
            using (AdoDataConnection connection = new AdoDataConnection("systemSettings"))
            {
                List <int> channelIds = new TableOperations <Channel>(connection).QueryRecordsWhere("MeterID = {0} AND MeasurementCharacteristicID = (SELECT ID FROM MeasurementCharacteristic WHERE Name = 'TotalTHD')", assetGroup.Key).Select(x => x.ID).ToList();
                List <openHistorian.XDALink.TrendingDataPoint> historianPoints = new List <openHistorian.XDALink.TrendingDataPoint>();
                try
                {
                    using (Historian historian = new Historian(HistorianServer, HistorianInstance))
                    {
                        foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(channelIds, startDate, endDate))
                        {
                            if (point.Value < 0.1)
                            {
                                point.Value *= 100;
                            }
                            if (point.SeriesID.ToString() == "Average" && point.Value >= 0 && point.Value <= 10)
                            {
                                historianPoints.Add(point);
                            }
                        }

                        return("{" + string.Join(",", historianPoints.GroupBy(x => (int)(x.Value / 0.1)).Where(x => x.Key > 0).OrderBy(x => x.Key).Select(x => $"\"{x.Key}\":\"{x.Count()}\"")) + "}");
                    }
                }
                catch (KeyNotFoundException ex)
                {
                    return("");
                }
                catch (SocketException ex)
                {
                    return("");
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
Ejemplo n.º 3
0
        private void LoadRangeLimits(MeterDataSet meterDataSet)
        {
            Dictionary <Channel, List <DataGroup> > trendingGroups = meterDataSet.GetResource <TrendingGroupsResource>().TrendingGroups;

            DateTime startTime = trendingGroups
                                 .SelectMany(kvp => kvp.Value)
                                 .Select(dataGroup => dataGroup.StartTime)
                                 .DefaultIfEmpty(DateTime.MaxValue)
                                 .Min().Date;

            DateTime endTime = trendingGroups
                               .SelectMany(kvp => kvp.Value)
                               .Select(dataGroup => dataGroup.EndTime)
                               .DefaultIfEmpty(DateTime.MinValue)
                               .Max();

            if (endTime != endTime.Date)
            {
                endTime = endTime.Date.AddDays(1.0D);
            }

            int days = (int)Math.Ceiling((endTime - startTime).TotalDays);

            if (days < 0)
            {
                return;
            }

            using (AdoDataConnection connection = meterDataSet.CreateDbConnection())
                using (Historian historian = new Historian(m_historianSettings.Server, m_historianSettings.InstanceName))
                {
                    TableOperations <ChannelAlarmSummary> channelAlarmSummaryTable = new TableOperations <ChannelAlarmSummary>(connection);
                    TableOperations <MeterAlarmSummary>   meterAlarmSummaryTable   = new TableOperations <MeterAlarmSummary>(connection);

                    Dictionary <int, Channel> channelLookup = meterDataSet.Meter.Channels
                                                              .Where(channel => channel.ID > 0)
                                                              .ToDictionary(channel => channel.ID);

                    for (int i = 0; i < days; i++)
                    {
                        DateTime queryStart = startTime.AddDays(i);
                        DateTime queryEnd   = queryStart.AddDays(1.0D).AddTicks(-1L);

                        List <ChannelAlarmSummary> channelAlarmSummaries = historian.Read(meterDataSet.Meter.Channels.Select(channel => channel.ID), queryStart, queryEnd)
                                                                           .Where(trendingPoint => trendingPoint.SeriesID == SeriesID.Average)
                                                                           .GroupBy(trendingPoint => trendingPoint.ChannelID)
                                                                           .SelectMany(channelGroup =>
                        {
                            Channel channel = channelLookup[channelGroup.Key];
                            List <AlarmRangeLimit> alarmRangeLimits = InitializeRangeLimitTable(connection, channel);

                            return(channelGroup
                                   .SelectMany(TrendingPoint => alarmRangeLimits.Where(rangeLimit => rangeLimit.Enabled).Select(RangeLimit => new { TrendingPoint, RangeLimit }))
                                   .Where(obj => CheckAlarm(channel, obj.TrendingPoint, obj.RangeLimit))
                                   .GroupBy(obj => obj.RangeLimit.AlarmTypeID)
                                   .Select(alarmTypeGroup => CreateChannelAlarmSummary(channelGroup.Key, alarmTypeGroup.Key, queryStart, alarmTypeGroup.Count())));
                        })
                                                                           .ToList();

                        List <MeterAlarmSummary> meterAlarmSummaries = channelAlarmSummaries
                                                                       .GroupBy(channelAlarmSummary => channelAlarmSummary.AlarmTypeID)
                                                                       .Select(channelSummaryGroup => CreateMeterAlarmSummary(meterDataSet.Meter.ID, channelSummaryGroup.Key, queryStart, channelSummaryGroup.Sum(channelAlarmSummary => channelAlarmSummary.AlarmPoints)))
                                                                       .ToList();

                        foreach (MeterAlarmSummary meterAlarmSummary in meterAlarmSummaries)
                        {
                            meterAlarmSummaryTable.Upsert(meterAlarmSummary);
                        }

                        foreach (ChannelAlarmSummary channelAlarmSummary in channelAlarmSummaries)
                        {
                            channelAlarmSummaryTable.Upsert(channelAlarmSummary);
                        }
                    }
                }
        }
Ejemplo n.º 4
0
        private void LoadRangeLimits(MeterDataSet meterDataSet)
        {
            MeterAlarmSummaryTableAdapter   meterAlarmSummaryAdapter;
            ChannelAlarmSummaryTableAdapter channelAlarmSummaryAdapter;
            HourOfWeekLimitTableAdapter     hourlyLimitAdapter;

            MeterAlarmSummaryDataTable   meterAlarmSummaryTable;
            ChannelAlarmSummaryDataTable channelAlarmSummaryTable;

            Dictionary <Channel, List <DataGroup> > trendingGroups;

            DateTime startTime;
            DateTime endTime;
            int      days;

            meterAlarmSummaryAdapter   = m_dbAdapterContainer.GetAdapter <MeterAlarmSummaryTableAdapter>();
            channelAlarmSummaryAdapter = m_dbAdapterContainer.GetAdapter <ChannelAlarmSummaryTableAdapter>();
            hourlyLimitAdapter         = m_dbAdapterContainer.GetAdapter <HourOfWeekLimitTableAdapter>();

            meterAlarmSummaryTable   = new MeterAlarmSummaryDataTable();
            channelAlarmSummaryTable = new ChannelAlarmSummaryDataTable();

            trendingGroups = meterDataSet.GetResource <TrendingGroupsResource>().TrendingGroups;

            startTime = trendingGroups
                        .SelectMany(kvp => kvp.Value)
                        .Select(dataGroup => dataGroup.StartTime)
                        .DefaultIfEmpty(DateTime.MaxValue)
                        .Min().Date;

            endTime = trendingGroups
                      .SelectMany(kvp => kvp.Value)
                      .Select(dataGroup => dataGroup.EndTime)
                      .DefaultIfEmpty(DateTime.MinValue)
                      .Max();

            if (endTime != endTime.Date)
            {
                endTime = endTime.Date.AddDays(1.0D);
            }

            days = (int)Math.Ceiling((endTime - startTime).TotalDays);

            if (days < 0)
            {
                return;
            }

            using (Historian historian = new Historian(m_historianSettings.Server, m_historianSettings.InstanceName))
            {
                for (int i = 0; i < days; i++)
                {
                    DateTime queryStart = startTime.AddDays(i);
                    DateTime queryEnd   = queryStart.AddDays(1.0D).AddTicks(-1L);

                    List <ChannelAlarmSummaryRow> channelAlarmSummaries = historian.Read(meterDataSet.Meter.Channels.Select(channel => channel.ID), queryStart, queryEnd)
                                                                          .Where(trendingPoint => trendingPoint.SeriesID == SeriesID.Average)
                                                                          .GroupBy(trendingPoint => trendingPoint.ChannelID)
                                                                          .SelectMany(channelGroup =>
                    {
                        Channel channel = m_dbAdapterContainer.GetAdapter <MeterInfoDataContext>().Channels.Single(ch => ch.ID == channelGroup.Key);
                        AlarmRangeLimitDataTable rangeLimitTable = InitializeRangeLimitTable(channel);

                        return(channelGroup
                               .SelectMany(TrendingPoint => rangeLimitTable.Where(rangeLimit => rangeLimit.Enabled != 0).Select(RangeLimit => new { TrendingPoint, RangeLimit }))
                               .Where(obj => CheckAlarm(channel, obj.TrendingPoint, obj.RangeLimit))
                               .GroupBy(obj => obj.RangeLimit.AlarmTypeID)
                               .Select(alarmTypeGroup => CreateSummaryRow(channelAlarmSummaryTable, channelGroup.Key, alarmTypeGroup.Key, queryStart, alarmTypeGroup.Count())));
                    })
                                                                          .ToList();

                    IEnumerable <MeterAlarmSummaryRow> meterAlarmSummaries = channelAlarmSummaries
                                                                             .GroupBy(channelAlarmSummary => channelAlarmSummary.AlarmTypeID)
                                                                             .Select(channelSummaryGroup => CreateSummaryRow(meterAlarmSummaryTable, meterDataSet.Meter.ID, channelSummaryGroup.Key, queryStart, channelSummaryGroup.Sum(channelAlarmSummary => channelAlarmSummary.AlarmPoints)));

                    foreach (MeterAlarmSummaryRow meterAlarmSummary in meterAlarmSummaries)
                    {
                        meterAlarmSummaryAdapter.Upsert(meterAlarmSummary);
                    }

                    foreach (ChannelAlarmSummaryRow channelAlarmSummary in channelAlarmSummaries)
                    {
                        channelAlarmSummaryAdapter.Upsert(channelAlarmSummary);
                    }
                }
            }
        }
Ejemplo n.º 5
0
        private void LoadHourOfWeekLimits(MeterDataSet meterDataSet)
        {
            TrendingGroupsResource trendingGroupsResource          = meterDataSet.GetResource <TrendingGroupsResource>();
            Dictionary <Channel, List <DataGroup> > trendingGroups = trendingGroupsResource.TrendingGroups;

            DateTime startTime = trendingGroups
                                 .SelectMany(kvp => kvp.Value)
                                 .Select(dataGroup => dataGroup.StartTime)
                                 .DefaultIfEmpty(DateTime.MaxValue)
                                 .Min();

            DateTime endTime = trendingGroups
                               .SelectMany(kvp => kvp.Value)
                               .Select(dataGroup => dataGroup.EndTime)
                               .DefaultIfEmpty(DateTime.MinValue)
                               .Max();

            int days = (int)Math.Ceiling((endTime - startTime).TotalDays);

            if (days < 0)
            {
                return;
            }

            using (Historian historian = new Historian(m_historianSettings.Server, m_historianSettings.InstanceName))
                using (AdoDataConnection connection = meterDataSet.CreateDbConnection())
                {
                    TableOperations <HourOfWeekLimit>     hourOfWeekLimitTable     = new TableOperations <HourOfWeekLimit>(connection);
                    TableOperations <MeterAlarmSummary>   meterAlarmSummaryTable   = new TableOperations <MeterAlarmSummary>(connection);
                    TableOperations <ChannelAlarmSummary> channelAlarmSummaryTable = new TableOperations <ChannelAlarmSummary>(connection);

                    for (int i = 0; i < days; i++)
                    {
                        DateTime queryStart = startTime.AddDays(days);
                        DateTime queryEnd   = queryStart.AddDays(1.0D).AddTicks(-1L);

                        List <ChannelAlarmSummary> channelAlarmSummaries = historian.Read(meterDataSet.Meter.Channels.Select(channel => channel.ID), queryStart, queryEnd)
                                                                           .Where(trendingPoint => trendingPoint.SeriesID == SeriesID.Average)
                                                                           .GroupBy(trendingPoint => trendingPoint.ChannelID)
                                                                           .SelectMany(channelGroup =>
                        {
                            List <HourOfWeekLimit> hourOfWeekLimits = hourOfWeekLimitTable
                                                                      .QueryRecordsWhere("ChannelID = {0}", channelGroup.Key)
                                                                      .ToList();

                            return(channelGroup
                                   .Join(hourOfWeekLimits, trendingPoint => GetHourOfWeek(trendingPoint.Timestamp), hourlyLimit => hourlyLimit.HourOfWeek, (TrendingPoint, HourlyLimit) => new { TrendingPoint, HourlyLimit })
                                   .Where(obj => obj.TrendingPoint.Value <obj.HourlyLimit.Low || obj.TrendingPoint.Value> obj.HourlyLimit.High)
                                   .GroupBy(obj => obj.HourlyLimit.AlarmTypeID)
                                   .Select(alarmTypeGroup => CreateChannelAlarmSummary(channelGroup.Key, alarmTypeGroup.Key, queryStart, alarmTypeGroup.Count())));
                        })
                                                                           .ToList();

                        List <MeterAlarmSummary> meterAlarmSummaries = channelAlarmSummaries
                                                                       .GroupBy(channelAlarmSummary => channelAlarmSummary.AlarmTypeID)
                                                                       .Select(channelSummaryGroup => CreateMeterAlarmSummary(meterDataSet.Meter.ID, channelSummaryGroup.Key, queryStart, channelSummaryGroup.Sum(channelAlarmSummary => channelAlarmSummary.AlarmPoints)))
                                                                       .ToList();

                        foreach (MeterAlarmSummary meterAlarmSummary in meterAlarmSummaries)
                        {
                            meterAlarmSummaryTable.Upsert(meterAlarmSummary);
                        }

                        foreach (ChannelAlarmSummary channelAlarmSummary in channelAlarmSummaries)
                        {
                            channelAlarmSummaryTable.Upsert(channelAlarmSummary);
                        }
                    }
                }
        }
Ejemplo n.º 6
0
        public IHttpActionResult Get(int channelID, string date)
        {
            try
            {
                string            historianServer;
                string            historianInstance;
                IEnumerable <int> channelIDs = new List <int>()
                {
                    channelID
                };
                DateTime        startDate       = Convert.ToDateTime(date);
                DateTime        endDate         = startDate.AddDays(1);
                TrendingDataSet trendingDataSet = new TrendingDataSet();
                DateTime        epoch           = new DateTime(1970, 1, 1);

                using (AdoDataConnection connection = new AdoDataConnection("dbOpenXDA"))
                {
                    historianServer   = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
                    historianInstance = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.InstanceName'") ?? "XDA";

                    using (Historian historian = new Historian(historianServer, historianInstance))
                    {
                        foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(channelIDs, startDate, endDate))
                        {
                            if (!trendingDataSet.ChannelData.Exists(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds))
                            {
                                trendingDataSet.ChannelData.Add(new TrendingDataDatum());
                                trendingDataSet.ChannelData[trendingDataSet.ChannelData.Count - 1].Time = point.Timestamp.Subtract(epoch).TotalMilliseconds;
                            }

                            if (point.SeriesID.ToString() == "Average")
                            {
                                trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Average = point.Value;
                            }
                            else if (point.SeriesID.ToString() == "Minimum")
                            {
                                trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Minimum = point.Value;
                            }
                            else if (point.SeriesID.ToString() == "Maximum")
                            {
                                trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Maximum = point.Value;
                            }
                        }
                    }
                    IEnumerable <DataRow> table = Enumerable.Empty <DataRow>();

                    table = connection.RetrieveData(" Select {0} AS thedatefrom, " +
                                                    "        DATEADD(DAY, 1, {0}) AS thedateto, " +
                                                    "        CASE WHEN AlarmRangeLimit.PerUnit <> 0 AND Channel.PerUnitValue IS NOT NULL THEN AlarmRangeLimit.High * PerUnitValue ELSE AlarmRangeLimit.High END AS alarmlimithigh," +
                                                    "        CASE WHEN AlarmRangeLimit.PerUnit <> 0 AND Channel.PerUnitValue IS NOT NULL THEN AlarmRangeLimit.Low * PerUnitValue ELSE AlarmRangeLimit.Low END AS alarmlimitlow " +
                                                    " FROM   AlarmRangeLimit JOIN " +
                                                    "        Channel ON AlarmRangeLimit.ChannelID = Channel.ID " +
                                                    "WHERE   AlarmRangeLimit.AlarmTypeID = (SELECT ID FROM AlarmType where Name = 'Alarm') AND " +
                                                    "        AlarmRangeLimit.ChannelID = {1}", startDate, channelID).Select();

                    foreach (DataRow row in table)
                    {
                        trendingDataSet.AlarmLimits.Add(new TrendingAlarmLimit()
                        {
                            High = row.Field <double?>("alarmlimithigh"), Low = row.Field <double?>("alarmlimitlow"), TimeEnd = row.Field <DateTime>("thedateto").Subtract(epoch).TotalMilliseconds, TimeStart = row.Field <DateTime>("thedatefrom").Subtract(epoch).TotalMilliseconds
                        });
                    }

                    table = Enumerable.Empty <DataRow>();

                    table = connection.RetrieveData(" DECLARE @dayOfWeek INT = DATEPART(DW, {0}) - 1 " +
                                                    " DECLARE @hourOfWeek INT = @dayOfWeek * 24 " +
                                                    " ; WITH HourlyIndex AS" +
                                                    " ( " +
                                                    "   SELECT @hourOfWeek AS HourOfWeek " +
                                                    "   UNION ALL " +
                                                    "   SELECT HourOfWeek + 1 " +
                                                    "   FROM HourlyIndex" +
                                                    "   WHERE (HourOfWeek + 1) < @hourOfWeek + 24" +
                                                    " ) " +
                                                    " SELECT " +
                                                    "        DATEADD(HOUR, HourlyIndex.HourOfWeek - @hourOfWeek, {0}) AS thedatefrom, " +
                                                    "        DATEADD(HOUR, HourlyIndex.HourOfWeek - @hourOfWeek + 1, {0}) AS thedateto, " +
                                                    "        HourOfWeekLimit.High AS offlimithigh, " +
                                                    "        HourOfWeekLimit.Low AS offlimitlow " +
                                                    " FROM " +
                                                    "        HourlyIndex LEFT OUTER JOIN " +
                                                    "        HourOfWeekLimit ON HourOfWeekLimit.HourOfWeek = HourlyIndex.HourOfWeek " +
                                                    " WHERE " +
                                                    "        HourOfWeekLimit.ChannelID IS NULL OR " +
                                                    "        HourOfWeekLimit.ChannelID = {1} ", startDate, channelID).Select();

                    foreach (DataRow row in table)
                    {
                        trendingDataSet.OffNormalLimits.Add(new TrendingAlarmLimit()
                        {
                            High = row.Field <double?>("offlimithigh"), Low = row.Field <double?>("offlimitlow"), TimeEnd = row.Field <DateTime>("thedateto").Subtract(epoch).TotalMilliseconds, TimeStart = row.Field <DateTime>("thedatefrom").Subtract(epoch).TotalMilliseconds
                        });
                    }
                }


                return(Ok(trendingDataSet));
            }
            catch (Exception ex)
            {
                return(InternalServerError(ex));
            }
        }
Ejemplo n.º 7
0
    private List <List <TrendingDataLocation> > GetFramesFromHistorian(ContourQuery contourQuery)
    {
        DataTable idTable;
        string    historianServer;
        string    historianInstance;

        using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
        {
            var meters = (new TableOperations <Meter>(connection)).QueryRecordsWhere("ID IN (SELECT MeterID FROM MeterAssetGroup WHERE AssetGroupID IN (SELECT AssetGroupID FROM UserAccountAssetGroup WHERE UserAccountID =  (SELECT ID FROM UserAccount WHERE Name = {0})))", contourQuery.UserName);

            if (!string.IsNullOrEmpty(contourQuery.Meters))
            {
                const int byteSize = 8;

                // Meter selections are stored as a base-64 string without padding, using '-' instead of '+' and '_' instead of '/'
                string padding         = "A===".Remove(3 - (contourQuery.Meters.Length + 3) % 4);
                string base64          = contourQuery.Meters.Replace('-', '+').Replace('_', '/') + padding;
                byte[] meterSelections = Convert.FromBase64String(base64);
                var    ids             = string.Join("", meterSelections.Select(x => Convert.ToString(x, 2)));


                // The resulting byte array is a simple set of bitflags ordered by meter ID and packed into the most significant bits.
                // In order to properly interpret the bytes, we must first order the data by meter ID to determine the location of
                // each meter's bitflag. Then we can filter out the unwanted data from the original list of meters
                meters = meters
                         .OrderBy(meter => meter.ID)
                         .Where((meter, index) => (meterSelections[index / byteSize] & (0x80 >> (index % byteSize))) > 0)
                         .ToList();
            }


            string query =
                "SELECT " +
                "    Channel.ID AS ChannelID, " +
                "    Meter.ID AS MeterID, " +
                "    Meter.Name AS MeterName, " +
                "    MeterLocation.Latitude, " +
                "    MeterLocation.Longitude, " +
                "    Channel.PerUnitValue " +
                "FROM " +
                "    Meter JOIN " +
                "    MeterLocation ON Meter.MeterLocationID = MeterLocation.ID LEFT OUTER JOIN " +
                "    Channel ON " +
                "        Channel.MeterID = Meter.ID AND " +
                "        Channel.ID IN (SELECT ChannelID FROM ContourChannel WHERE ContourColorScaleName = {1}) " +
                "WHERE Meter.ID IN (" + string.Join(",", meters.Select(x => x.ID)) + ")";

            idTable           = connection.RetrieveData(query, contourQuery.UserName, contourQuery.ColorScaleName);
            historianServer   = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
            historianInstance = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.InstanceName'") ?? "XDA";
        }

        //if (!string.IsNullOrEmpty(contourQuery.Meters))
        //{
        //    const int byteSize = 8;

        //    // Meter selections are stored as a base-64 string without padding, using '-' instead of '+' and '_' instead of '/'
        //    string padding = "A===".Remove(3 - (contourQuery.Meters.Length + 3) % 4);
        //    string base64 = contourQuery.Meters.Replace('-', '+').Replace('_', '/') + padding;
        //    byte[] meterSelections = Convert.FromBase64String(base64);

        //    // The resulting byte array is a simple set of bitflags ordered by meter ID and packed into the most significant bits.
        //    // In order to properly interpret the bytes, we must first group and order the data by meter ID to determine the location
        //    // of each meter's bitflag. Then we can filter out the unwanted data from the original table of IDs
        //    idTable.Select()
        //        .Select((Row, Index) => new { Row, Index })
        //        .GroupBy(obj => obj.Row.ConvertField<int>("MeterID"))
        //        .OrderBy(grouping => grouping.Key)
        //        .Where((grouping, index) => (meterSelections[index / byteSize] & (0x80 >> (index % byteSize))) == 0)
        //        .SelectMany(grouping => grouping)
        //        .OrderByDescending(obj => obj.Index)
        //        .ToList()
        //        .ForEach(obj => idTable.Rows.RemoveAt(obj.Index));
        //}

        List <DataRow> meterRows = idTable
                                   .Select()
                                   .DistinctBy(row => row.ConvertField <int>("MeterID"))
                                   .ToList();

        DateTime startDate = contourQuery.GetStartDate();
        DateTime endDate   = contourQuery.GetEndDate();
        int      stepSize  = contourQuery.StepSize;

        // The frames to be included are those whose timestamps fall
        // within the range which is specified by startDate and
        // endDate. We start by aligning startDate and endDate with
        // the nearest frame timestamps which fall within that range
        int startTimeOffset = (int)Math.Ceiling((startDate - startDate.Date).TotalMinutes / stepSize);

        startDate = startDate.Date.AddMinutes(startTimeOffset * stepSize);

        int endTimeOffset = (int)Math.Floor((endDate - endDate.Date).TotalMinutes / stepSize);

        endDate = endDate.Date.AddMinutes(endTimeOffset * stepSize);

        // Since each frame includes data from all timestamps between
        // the previous frame's timestamp and its own timestamp, we
        // must include one additional frame of data before startDate
        startDate = startDate.AddMinutes(-stepSize);

        int frameCount = (int)((endDate - startDate).TotalMinutes / stepSize);

        List <Dictionary <int, TrendingDataLocation> > frames = Enumerable.Repeat(meterRows, frameCount)
                                                                .Select(rows => rows.Select(row => new TrendingDataLocation()
        {
            ID        = row.ConvertField <int>("MeterID"),
            Name      = row.ConvertField <string>("MeterName"),
            Latitude  = row.ConvertField <double>("Latitude"),
            Longitude = row.ConvertField <double>("Longitude")
        }))
                                                                .Select(locations => locations.ToDictionary(location => location.ID))
                                                                .ToList();

        Dictionary <int, double?> nominalLookup = idTable
                                                  .Select("ChannelID IS NOT NULL")
                                                  .ToDictionary(row => row.ConvertField <int>("ChannelID"), row => row.ConvertField <double?>("PerUnitValue"));

        Dictionary <int, List <TrendingDataLocation> > lookup = idTable
                                                                .Select("ChannelID IS NOT NULL")
                                                                .Select(row =>
        {
            int meterID = row.ConvertField <int>("MeterID");

            return(new
            {
                ChannelID = row.ConvertField <int>("ChannelID"),
                Frames = frames.Select(locationLookup => locationLookup[meterID]).ToList()
            });
        })
                                                                .ToDictionary(obj => obj.ChannelID, obj => obj.Frames);

        using (Historian historian = new Historian(historianServer, historianInstance))
        {
            foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(lookup.Keys, startDate, endDate))
            {
                List <TrendingDataLocation> locations = lookup[point.ChannelID];

                // Use ceiling to sort data into the next nearest frame.
                // Subtract 1 because startDate was shifted to include one additional frame of data
                int frameIndex = (int)Math.Ceiling((point.Timestamp - startDate).TotalMinutes / stepSize) - 1;

                if (frameIndex < 0 || frameIndex >= locations.Count)
                {
                    continue;
                }

                TrendingDataLocation frame = locations[frameIndex];

                double nominal = nominalLookup[point.ChannelID] ?? 1.0D;
                double value   = point.Value / nominal;

                switch (point.SeriesID)
                {
                case SeriesID.Minimum:
                    frame.Minimum = Math.Min(value, frame.Minimum ?? value);
                    break;

                case SeriesID.Maximum:
                    frame.Maximum = Math.Max(value, frame.Maximum ?? value);
                    break;

                case SeriesID.Average:
                    frame.Aggregate(value);
                    frame.Average = frame.GetAverage();
                    break;
                }
            }
        }

        return(frames
               .Select(frame => frame.Values.ToList())
               .ToList());
    }
    private List<List<TrendingDataLocation>> GetFramesFromHistorian(ContourQuery contourQuery)
    {
        DataTable idTable;
        string historianServer;
        string historianInstance;

        using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
        {
            string query =
                "SELECT " +
                "    Channel.ID AS ChannelID, " +
                "    Meter.ID AS MeterID, " +
                "    Meter.Name AS MeterName, " +
                "    MeterLocation.Latitude, " +
                "    MeterLocation.Longitude, " +
                "    Channel.PerUnitValue " +
                "FROM " +
                "    Meter JOIN " +
                "    MeterLocation ON Meter.MeterLocationID = MeterLocation.ID LEFT OUTER JOIN " +
                "    Channel ON " +
                "        Channel.MeterID = Meter.ID AND " +
                "        Channel.ID IN (SELECT ChannelID FROM ContourChannel WHERE ContourColorScaleName = {1}) " +
                "WHERE " +
                "    Meter.ID IN (SELECT * FROM authMeters({0}))";

            idTable = connection.RetrieveData(query, contourQuery.UserName, contourQuery.ColorScaleName);
            historianServer = connection.ExecuteScalar<string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
            historianInstance = connection.ExecuteScalar<string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";
        }

        List<DataRow> meterRows = idTable
            .Select()
            .DistinctBy(row => row.ConvertField<int>("MeterID"))
            .ToList();

        DateTime startDate = contourQuery.GetStartDate();
        DateTime endDate = contourQuery.GetEndDate();
        int stepSize = contourQuery.StepSize;

        // The frames to be included are those whose timestamps fall
        // within the range which is specified by startDate and
        // endDate. We start by aligning startDate and endDate with
        // the nearest frame timestamps which fall within that range
        int startTimeOffset = (int)Math.Ceiling((startDate - startDate.Date).TotalMinutes / stepSize);
        startDate = startDate.Date.AddMinutes(startTimeOffset * stepSize);

        int endTimeOffset = (int)Math.Floor((endDate - endDate.Date).TotalMinutes / stepSize);
        endDate = endDate.Date.AddMinutes(endTimeOffset * stepSize);

        // Since each frame includes data from all timestamps between
        // the previous frame's timestamp and its own timestamp, we
        // must include one additional frame of data before startDate
        startDate = startDate.AddMinutes(-stepSize);

        int frameCount = (int)((endDate - startDate).TotalMinutes / stepSize);

        List<Dictionary<int, TrendingDataLocation>> frames = Enumerable.Repeat(meterRows, frameCount)
            .Select(rows => rows.Select(row => new TrendingDataLocation()
            {
                id = row.ConvertField<int>("MeterID"),
                name = row.ConvertField<string>("MeterName"),
                Latitude = row.ConvertField<double>("Latitude"),
                Longitude = row.ConvertField<double>("Longitude")
            }))
            .Select(locations => locations.ToDictionary(location => location.id))
            .ToList();

        Dictionary<int, double?> nominalLookup = idTable
            .Select("ChannelID IS NOT NULL")
            .ToDictionary(row => row.ConvertField<int>("ChannelID"), row => row.ConvertField<double?>("PerUnitValue"));

        Dictionary<int, List<TrendingDataLocation>> lookup = idTable
            .Select("ChannelID IS NOT NULL")
            .Select(row =>
            {
                int meterID = row.ConvertField<int>("MeterID");

                return new
                {
                    ChannelID = row.ConvertField<int>("ChannelID"),
                    Frames = frames.Select(locationLookup => locationLookup[meterID]).ToList()
                };
            })
            .ToDictionary(obj => obj.ChannelID, obj => obj.Frames);

        using (Historian historian = new Historian(historianServer, historianInstance))
        {
            foreach (TrendingDataPoint point in historian.Read(lookup.Keys, startDate, endDate))
            {
                List<TrendingDataLocation> locations = lookup[point.ChannelID];

                // Use ceiling to sort data into the next nearest frame.
                // Subtract 1 because startDate was shifted to include one additional frame of data
                int frameIndex = (int)Math.Ceiling((point.Timestamp - startDate).TotalMinutes / stepSize) - 1;

                if (frameIndex < 0 || frameIndex >= locations.Count)
                    continue;

                TrendingDataLocation frame = locations[frameIndex];

                double nominal = nominalLookup[point.ChannelID] ?? 1.0D;
                double value = point.Value / nominal;

                switch (point.SeriesID)
                {
                    case SeriesID.Minimum:
                        frame.Minimum = Math.Min(value, frame.Minimum ?? value);
                        break;

                    case SeriesID.Maximum:
                        frame.Maximum = Math.Max(value, frame.Maximum ?? value);
                        break;

                    case SeriesID.Average:
                        frame.Aggregate(value);
                        frame.Average = frame.GetAverage();
                        break;
                }
            }
        }

        return frames
            .Select(frame => frame.Values.ToList())
            .ToList();
    }
Ejemplo n.º 9
0
        public TrendingDataSet GetData()
        {
            TrendingDataSet             trendingDataSet = new TrendingDataSet();
            Dictionary <string, string> query           = Request.QueryParameters();
            IEnumerable <int>           channelIDs      = new List <int>()
            {
                Convert.ToInt32(query["ChannelID"])
            };
            string   channelID = query["ChannelID"];
            DateTime startDate = Convert.ToDateTime(query["targetDate"]);

            string target = query["ChannelID"] + query["targetDate"];

            if (s_memoryCache.Contains(target))
            {
                return((TrendingDataSet)s_memoryCache.Get(target));
            }

            string   historianServer   = m_dataContext.Connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
            string   historianInstance = m_dataContext.Connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";
            DateTime endDate           = startDate.AddDays(1);
            DateTime epoch             = new DateTime(1970, 1, 1);

            using (Historian historian = new Historian(historianServer, historianInstance))
            {
                foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(channelIDs, startDate, endDate))
                {
                    if (!trendingDataSet.ChannelData.Exists(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds))
                    {
                        trendingDataSet.ChannelData.Add(new openXDA.Model.TrendingDataPoint());
                        trendingDataSet.ChannelData[trendingDataSet.ChannelData.Count - 1].Time = point.Timestamp.Subtract(epoch).TotalMilliseconds;
                    }

                    if (point.SeriesID.ToString() == "Average")
                    {
                        trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Average = point.Value;
                    }
                    else if (point.SeriesID.ToString() == "Minimum")
                    {
                        trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Minimum = point.Value;
                    }
                    else if (point.SeriesID.ToString() == "Maximum")
                    {
                        trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Maximum = point.Value;
                    }
                }
            }
            IEnumerable <DataRow> table = Enumerable.Empty <DataRow>();

            table = m_dataContext.Connection.RetrieveData(" Select {0} AS thedatefrom, " +
                                                          "        DATEADD(DAY, 1, {0}) AS thedateto, " +
                                                          "        CASE WHEN AlarmRangeLimit.PerUnit <> 0 AND Channel.PerUnitValue IS NOT NULL THEN AlarmRangeLimit.High * PerUnitValue ELSE AlarmRangeLimit.High END AS alarmlimithigh," +
                                                          "        CASE WHEN AlarmRangeLimit.PerUnit <> 0 AND Channel.PerUnitValue IS NOT NULL THEN AlarmRangeLimit.Low * PerUnitValue ELSE AlarmRangeLimit.Low END AS alarmlimitlow " +
                                                          " FROM   AlarmRangeLimit JOIN " +
                                                          "        Channel ON AlarmRangeLimit.ChannelID = Channel.ID " +
                                                          "WHERE   AlarmRangeLimit.AlarmTypeID = (SELECT ID FROM AlarmType where Name = 'Alarm') AND " +
                                                          "        AlarmRangeLimit.ChannelID = {1}", startDate, Convert.ToInt32(channelID)).Select();

            foreach (DataRow row in table)
            {
                trendingDataSet.AlarmLimits.Add(new TrendingAlarmLimit()
                {
                    High = row.Field <double?>("alarmlimithigh"), Low = row.Field <double?>("alarmlimitlow"), TimeEnd = row.Field <DateTime>("thedateto").Subtract(epoch).TotalMilliseconds, TimeStart = row.Field <DateTime>("thedatefrom").Subtract(epoch).TotalMilliseconds
                });
            }

            table = Enumerable.Empty <DataRow>();

            table = m_dataContext.Connection.RetrieveData(" DECLARE @dayOfWeek INT = DATEPART(DW, {0}) - 1 " +
                                                          " DECLARE @hourOfWeek INT = @dayOfWeek * 24 " +
                                                          " ; WITH HourlyIndex AS" +
                                                          " ( " +
                                                          "   SELECT @hourOfWeek AS HourOfWeek " +
                                                          "   UNION ALL " +
                                                          "   SELECT HourOfWeek + 1 " +
                                                          "   FROM HourlyIndex" +
                                                          "   WHERE (HourOfWeek + 1) < @hourOfWeek + 24" +
                                                          " ) " +
                                                          " SELECT " +
                                                          "        DATEADD(HOUR, HourlyIndex.HourOfWeek - @hourOfWeek, {0}) AS thedatefrom, " +
                                                          "        DATEADD(HOUR, HourlyIndex.HourOfWeek - @hourOfWeek + 1, {0}) AS thedateto, " +
                                                          "        HourOfWeekLimit.High AS offlimithigh, " +
                                                          "        HourOfWeekLimit.Low AS offlimitlow " +
                                                          " FROM " +
                                                          "        HourlyIndex LEFT OUTER JOIN " +
                                                          "        HourOfWeekLimit ON HourOfWeekLimit.HourOfWeek = HourlyIndex.HourOfWeek " +
                                                          " WHERE " +
                                                          "        HourOfWeekLimit.ChannelID IS NULL OR " +
                                                          "        HourOfWeekLimit.ChannelID = {1} ", startDate, Convert.ToInt32(channelID)).Select();

            foreach (DataRow row in table)
            {
                trendingDataSet.OffNormalLimits.Add(new TrendingAlarmLimit()
                {
                    High = row.Field <double?>("offlimithigh"), Low = row.Field <double?>("offlimitlow"), TimeEnd = row.Field <DateTime>("thedateto").Subtract(epoch).TotalMilliseconds, TimeStart = row.Field <DateTime>("thedatefrom").Subtract(epoch).TotalMilliseconds
                });
            }

            s_memoryCache.Add(target, trendingDataSet, new CacheItemPolicy()
            {
                SlidingExpiration = TimeSpan.FromMinutes(10.0D)
            });

            return(trendingDataSet);
        }
Ejemplo n.º 10
0
        public Task <Dictionary <string, List <double[]> > > GetData(CancellationToken cancellationToken)
        {
            Dictionary <string, string> query = Request.QueryParameters();
            int channelID = int.Parse(query["ChannelID"]);
            int pixels    = int.Parse(query["pixels"]);

            DateTime startDate = DateTime.ParseExact(query["StartDate"], "yyyy-MM-ddTHH:mm", CultureInfo.CurrentCulture);
            DateTime endDate   = DateTime.ParseExact(query["EndDate"], "yyyy-MM-ddTHH:mm", CultureInfo.CurrentCulture);
            DateTime epoch     = new DateTime(1970, 1, 1);

            return(Task.Factory.StartNew(() =>
            {
                using (AdoDataConnection connection = new AdoDataConnection("systemSettings"))
                {
                    string target = "TrendingDataDisplayGetData" + channelID.ToString() + startDate.ToString("yyyyMMddHHmm") + endDate.ToString("yyyyMMddHHmm");
                    Dictionary <string, List <double[]> > data = (Dictionary <string, List <double[]> >)s_memoryCache.Get(target);
                    if (data == null)
                    {
                        data = new Dictionary <string, List <double[]> >();
                        data.Add("Minimum", new List <double[]>());
                        data.Add("Maximum", new List <double[]>());
                        data.Add("Average", new List <double[]>());

                        string historianServer = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
                        string historianInstance = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";

                        using (Historian historian = new Historian(historianServer, historianInstance))
                        {
                            foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(new[] { channelID }, startDate, endDate))
                            {
                                data[point.SeriesID.ToString()].Add(new[] { point.Timestamp.Subtract(epoch).TotalMilliseconds, point.Value });
                            }
                        }

                        s_memoryCache.Add(target, data, new CacheItemPolicy {
                            SlidingExpiration = TimeSpan.FromMinutes(0.5D)
                        });
                    }
                    return Downsample(data, pixels, new Range <DateTime>(startDate, endDate));
                }
            }, cancellationToken));
        }
Ejemplo n.º 11
0
        public void ProcessMonthToDateData()
        {
            DateTime endDate   = DateTime.UtcNow;
            DateTime startDate = new DateTime(endDate.Year, endDate.Month, 1);


            string historianServer   = DataContext.Connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
            string historianInstance = DataContext.Connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";

            IEnumerable <PQMarkCompanyMeter> meters = DataContext.Table <PQMarkCompanyMeter>().QueryRecordsWhere("Enabled = 1");

            if (!meters.Any())
            {
                return;
            }

            DataTable table = DataContext.Connection.RetrieveData(
                @"SELECT	Event.MeterID, Disturbance.PerUnitMagnitude, Disturbance.StartTime, Disturbance.EndTime, Disturbance.DurationSeconds, Disturbance.DurationCycles
                  FROM      Disturbance JOIN
		                    Event ON Event.ID = Disturbance.EventID
                  WHERE	    Disturbance.PhaseID = (SELECT ID FROM Phase WHERE Name = 'Worst') AND
		                    Event.MeterID IN ("         + string.Join(",", meters.Select(x => x.MeterID)) + @") AND
                            Event.StartTime Between '" + startDate + @"' AND '" + endDate + @"'"
                );
            IEnumerable <DisturbanceData> dd = table.Select().Select(row => DataContext.Table <DisturbanceData>().LoadRecord(row));

            var meterGroups = dd.GroupBy(x => x.MeterID);

            foreach (var meterGroup in meterGroups)
            {
                OnLogStatusMessage(string.Format("PQMark aggregation: Processing {0}", meterGroup.Key));
                // Get Easy Counts for SARFI 90, 70, 50, 10
                int sarfi90 = meterGroup.Where(x => x.PerUnitMagnitude <= 0.9).Count();
                int sarfi70 = meterGroup.Where(x => x.PerUnitMagnitude <= 0.7).Count();
                int sarfi50 = meterGroup.Where(x => x.PerUnitMagnitude <= 0.5).Count();
                int sarfi10 = meterGroup.Where(x => x.PerUnitMagnitude <= 0.1).Count();

                // Get Counts for semi
                int semi = meterGroup.Where(x => {
                    double vc = 0.0D;

                    int point1 = Curves.SemiCurve.TakeWhile(y => y.Item2 < x.DurationSeconds).Count() - 1;
                    if (point1 == -1)
                    {
                        return(false);
                    }
                    else if (point1 + 1 == Curves.SemiCurve.Count())
                    {
                        vc = Curves.SemiCurve[point1].Item1;
                    }
                    else if (Curves.SemiCurve[point1].Item2 == Curves.SemiCurve[point1 + 1].Item2)
                    {
                        vc = Curves.SemiCurve[point1 + 1].Item1;
                    }
                    else
                    {
                        double slope = (Curves.SemiCurve[point1 + 1].Item1 - Curves.SemiCurve[point1].Item1) / (Curves.SemiCurve[point1 + 1].Item2 - Curves.SemiCurve[point1].Item2);
                        vc           = slope * (x.DurationSeconds - Curves.SemiCurve[point1].Item2) + Curves.SemiCurve[point1].Item1;
                    }
                    double value = (1.0D - x.PerUnitMagnitude) / (1.0D - vc);
                    return(value >= 1.0D);
                }).Count();

                // Get counts for ITIC
                int iticLower = meterGroup.Where(x => {
                    double vc = 0.0D;

                    int point1 = Curves.IticLowerCurve.TakeWhile(y => y.Item2 < x.DurationSeconds).Count() - 1;
                    if (point1 == -1)
                    {
                        return(false);
                    }
                    else if (point1 + 1 == Curves.IticLowerCurve.Count())
                    {
                        vc = Curves.IticLowerCurve[point1].Item1;
                    }
                    else if (Curves.IticLowerCurve[point1].Item2 == Curves.IticLowerCurve[point1 + 1].Item2)
                    {
                        vc = Curves.IticLowerCurve[point1 + 1].Item1;
                    }
                    else
                    {
                        double slope = (Curves.IticLowerCurve[point1 + 1].Item1 - Curves.IticLowerCurve[point1].Item1) / (Curves.IticLowerCurve[point1 + 1].Item2 - Curves.IticLowerCurve[point1].Item2);
                        vc           = slope * (x.DurationSeconds - Curves.IticLowerCurve[point1].Item2) + Curves.IticLowerCurve[point1].Item1;
                    }
                    double value = (1.0D - x.PerUnitMagnitude) / (1.0D - vc);
                    return(value >= 1.0D);
                }).Count();

                int iticUpper = meterGroup.Where(x => {
                    double vc = 0.0D;

                    int point1 = Curves.IticUpperCurve.TakeWhile(y => y.Item2 < x.DurationSeconds).Count() - 1;
                    if (point1 == -1)
                    {
                        return(false);
                    }
                    else if (point1 + 1 == Curves.IticUpperCurve.Count())
                    {
                        vc = Curves.IticUpperCurve[point1].Item1;
                    }
                    else if (Curves.IticUpperCurve[point1].Item2 == Curves.IticUpperCurve[point1 + 1].Item2)
                    {
                        vc = Curves.IticUpperCurve[point1 + 1].Item2;
                    }
                    else
                    {
                        double slope = (Curves.IticUpperCurve[point1 + 1].Item1 - Curves.IticUpperCurve[point1].Item1) / (Curves.IticUpperCurve[point1 + 1].Item2 - Curves.IticUpperCurve[point1].Item2);
                        vc           = slope * (x.DurationSeconds - Curves.IticUpperCurve[point1].Item2) + Curves.IticUpperCurve[point1].Item1;
                    }
                    double value = (1.0D - x.PerUnitMagnitude) / (1.0D - vc);
                    return(value >= 1.0D);
                }).Count();

                List <int> channelIds = DataContext.Table <Channel>().QueryRecordsWhere("MeterID = {0} AND MeasurementCharacteristicID = (SELECT ID FROM MeasurementCharacteristic WHERE Name = 'TotalTHD')", meterGroup.Key).Select(x => x.ID).ToList();
                List <openHistorian.XDALink.TrendingDataPoint> historianPoints = new List <openHistorian.XDALink.TrendingDataPoint>();
                using (Historian historian = new Historian(historianServer, historianInstance))
                {
                    foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(channelIds, startDate, endDate))
                    {
                        if (point.Value < 0.1)
                        {
                            point.Value *= 100;
                        }
                        if (point.SeriesID.ToString() == "Average" && point.Value >= 0 && point.Value <= 10)
                        {
                            historianPoints.Add(point);
                        }
                    }
                }

                string thdjson = "{" + string.Join(",", historianPoints.GroupBy(x => (int)(x.Value / 0.1)).Where(x => x.Key > 0).OrderBy(x => x.Key).Select(x => $"\"{x.Key}\":\"{x.Count()}\"")) + "}";

                PQMarkAggregate record = DataContext.Table <PQMarkAggregate>().QueryRecordWhere("MeterID = {0} AND Year = {1} AND Month = {2}", meterGroup.Key, startDate.Year, startDate.Month);
                if (record != null)
                {
                    record.ITIC    = iticLower + iticUpper;
                    record.SEMI    = semi;
                    record.SARFI90 = sarfi90;
                    record.SARFI70 = sarfi70;
                    record.SARFI50 = sarfi50;
                    record.SARFI10 = sarfi10;
                    record.THDJson = thdjson;

                    DataContext.Table <PQMarkAggregate>().UpdateRecord(record);
                }
                else
                {
                    record = new PQMarkAggregate()
                    {
                        MeterID = meterGroup.Key,
                        Year    = startDate.Year,
                        Month   = startDate.Month,
                        ITIC    = iticLower + iticUpper,
                        SEMI    = semi,
                        SARFI90 = sarfi90,
                        SARFI70 = sarfi70,
                        SARFI50 = sarfi50,
                        SARFI10 = sarfi10,
                        THDJson = thdjson
                    };

                    DataContext.Table <PQMarkAggregate>().AddNewRecord(record);
                }
            }

            OnLogStatusMessage(string.Format("PQMark data aggregation is complete..."));
        }
        public Task <string[][]> GetData(CancellationToken cancellationToken)
        {
            Dictionary <string, string> query = Request.QueryParameters();
            int      meterID   = int.Parse(query["meterID"]);
            string   level     = query["level"];
            string   type      = query["type"];
            int      phaseID   = int.Parse(query["phase"]);
            DateTime startTime = DateTime.ParseExact(query["date"] + "T00:00:00", "yyyy-MM-ddTHH:mm:ss", CultureInfo.CurrentCulture);
            DateTime endTime   = DateTime.ParseExact(query["date"] + "T23:59:59", "yyyy-MM-ddTHH:mm:ss", CultureInfo.CurrentCulture);

            return(Task.Factory.StartNew(() =>
            {
                using (AdoDataConnection connection = new AdoDataConnection("systemSettings"))
                {
                    string target = "SpectralDataDisplay" + meterID.ToString() + startTime.ToString("yyyyMMdd") + level + type + phaseID.ToString();
                    List <List <string> > data = (List <List <string> >)s_memoryCache.Get(target);
                    if (data == null)
                    {
                        Dictionary <DateTime, Dictionary <string, double> > dict = new Dictionary <DateTime, Dictionary <string, double> >();
                        IEnumerable <Channel> channels = (new TableOperations <Channel>(connection)).QueryRecords(GetRecordRestriction(meterID, phaseID, type));
                        IEnumerable <string> headers = channels.Select(x => GetBucket(type, x));
                        data = new List <List <string> >();

                        data.Add((new List <string>()
                        {
                            "TimeStamp"
                        }).Concat(headers).ToList());

                        string historianServer = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
                        string historianInstance = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";
                        using (Historian historian = new Historian(historianServer, historianInstance))
                        {
                            IEnumerable <IGrouping <DateTime, TrendingDataPoint> > points = historian.Read(channels.Select(x => x.ID).ToArray(), startTime, endTime).Where(x => x.SeriesID.ToString() == level).GroupBy(x => x.Timestamp);

                            foreach (var grouping in points)
                            {
                                dict.Add(grouping.Key, new Dictionary <string, double>());
                                foreach (TrendingDataPoint trendingDataPoint in grouping)
                                {
                                    dict[grouping.Key].Add(GetBucket(type, channels.First(x => x.ID == trendingDataPoint.ChannelID)), trendingDataPoint.Value);
                                }
                            }

                            foreach (var pair in dict)
                            {
                                List <string> row = new List <string>()
                                {
                                    pair.Key.ToString()
                                };
                                foreach (string header in headers)
                                {
                                    row.Add(pair.Value[header].ToString());
                                }

                                data.Add(row);
                            }
                        }

                        s_memoryCache.Add(target, data, new CacheItemPolicy {
                            SlidingExpiration = TimeSpan.FromMinutes(5.0D)
                        });
                    }
                    return data.Select(x => x.ToArray()).ToArray();
                }
            }, cancellationToken));
        }
Ejemplo n.º 13
0
        public void ProcessSmartAlarmsNormal(IEnumerable <int> meterIds, IEnumerable <int> typeIds, DateTime startDate, DateTime endDate, int sigmaLevel, int decimals, bool ignoreLargeValues, bool overwriteOldAlarms, int largeValueLevel)
        {
            int progressTotal = (meterIds.Any() ? meterIds.Count() : 1);
            int progressCount = 0;

            ProgressUpdatedOverall("", (int)(100 * (progressCount) / progressTotal));

            string historianServer   = DataContext.Connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
            string historianInstance = DataContext.Connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";

            foreach (int meterId in meterIds)
            {
                string            characteristicList = "(" + string.Join(",", typeIds) + ")";
                IEnumerable <int> channelIds         = DataContext.Table <Channel>().QueryRecordsWhere("MeterID = {0} AND MeasurementCharacteristicID IN " + characteristicList, meterId).Select(x => x.ID);
                string            meterName          = DataContext.Connection.ExecuteScalar <string>("Select Name from Meter where ID = {0}", meterId);
                ProgressUpdatedOverall(meterName, (int)(100 * (progressCount) / progressTotal));
                List <TrendingData>     trendingData      = new List <TrendingData>();
                List <RunningAvgStdDev> normalRunningData = new List <RunningAvgStdDev>();
                ProgressUpdatedByMeter("Querying openHistorian...", 0);
                using (openHistorian.XDALink.Historian historian = new Historian(historianServer, historianInstance))
                {
                    foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(channelIds, startDate, endDate))
                    {
                        RunningAvgStdDev normalRecord = normalRunningData.FirstOrDefault(x => x.ChannelID == point.ChannelID);
                        if (normalRecord == null)
                        {
                            normalRecord = new RunningAvgStdDev()
                            {
                                ChannelID    = point.ChannelID,
                                Count        = 0,
                                Sum          = 0,
                                SumOfSquares = 0
                            };
                            normalRunningData.Add(normalRecord);
                        }

                        if (point.SeriesID.ToString() == "Average")
                        {
                            normalRecord.Sum          += point.Value;
                            normalRecord.SumOfSquares += (point.Value * point.Value);
                            ++normalRecord.Count;
                        }
                    }

                    if (ignoreLargeValues)
                    {
                        normalRunningData = normalRunningData.Select(x =>
                        {
                            double average = x.Sum / (x.Count != 0 ? x.Count : 1);

                            x.FirstPassStdDev = Math.Sqrt(Math.Abs((x.SumOfSquares - 2 * average * x.Sum + x.Count * average * average) / ((x.Count != 1 ? x.Count : 2) - 1)));
                            x.Count           = 0;
                            x.Sum             = 0;
                            x.SumOfSquares    = 0;
                            return(x);
                        }).ToList();



                        ProgressUpdatedByMeter("Querying openHistorian for second pass...", 0);
                        foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(channelIds, startDate, endDate))
                        {
                            int hourOfWeek = (int)point.Timestamp.DayOfWeek * 24 + point.Timestamp.Hour;
                            RunningAvgStdDev normalRecord = normalRunningData.FirstOrDefault(x => x.ChannelID == point.ChannelID);
                            if ((point.SeriesID.ToString() == "Average" && point.Value > (normalRecord.FirstPassStdDev * largeValueLevel)) || (point.SeriesID.ToString() == "Average" && point.Value < (normalRecord.FirstPassStdDev * largeValueLevel)))
                            {
                                continue;
                            }
                            if (point.SeriesID.ToString() == "Average")
                            {
                                normalRecord.Sum          += point.Value;
                                normalRecord.SumOfSquares += (point.Value * point.Value);
                                ++normalRecord.Count;
                            }
                        }
                    }
                }

                int innerProgressTotal = (channelIds.Any() ? channelIds.Count() : 1);
                int innerProgressCount = 0;

                foreach (int channelId in channelIds)
                {
                    string channelName = DataContext.Connection.ExecuteScalar <string>("Select Name from Channel where ID = {0}", channelId);
                    ProgressUpdatedByMeter(channelName, (int)(100 * (innerProgressCount) / innerProgressTotal));
                    RunningAvgStdDev record = normalRunningData.Where(x => x.ChannelID == channelId).FirstOrDefault();
                    if (record != null)
                    {
                        double average = record.Sum / (record.Count != 0 ? record.Count : 1);

                        double stdDev = Math.Sqrt(Math.Abs((record.SumOfSquares - 2 * average * record.Sum + record.Count * average * average) / ((record.Count != 1 ? record.Count : 2) - 1)));
                        float  high   = (float)Math.Round(average + stdDev * sigmaLevel, decimals);
                        float  low    = (float)Math.Round(average - stdDev * sigmaLevel, decimals);

                        AlarmRangeLimit hwl = DataContext.Table <AlarmRangeLimit>().QueryRecordWhere("ChannelID = {0}", record.ChannelID);

                        if (hwl == null)
                        {
                            AlarmRangeLimit newRecord = new AlarmRangeLimit()
                            {
                                ChannelID      = record.ChannelID,
                                AlarmTypeID    = 5,
                                Severity       = 1,
                                High           = high,
                                Low            = low,
                                RangeInclusive = 0,
                                PerUnit        = 0,
                                Enabled        = 1,
                                IsDefault      = false
                            };
                            DataContext.Table <AlarmRangeLimit>().AddNewRecord(newRecord);
                        }
                        else if (hwl != null && overwriteOldAlarms)
                        {
                            hwl.High = high;
                            hwl.Low  = low;
                            DataContext.Table <AlarmRangeLimit>().UpdateRecord(hwl);
                        }
                    }

                    ProgressUpdatedByMeter(channelName, (int)(100 * (++innerProgressCount) / innerProgressTotal));
                }
                ProgressUpdatedOverall(meterName, (int)(100 * (++progressCount) / progressTotal));
            }
        }
        public Task <Dictionary <string, List <double[]> > > GetData(CancellationToken cancellationToken)
        {
            Dictionary <string, string> query = Request.QueryParameters();
            int meterId = int.Parse(query["MeterID"]);
            int measurementCharacteristicId = int.Parse(query["MeasurementCharacteristicID"]);
            int measurementTypeId           = int.Parse(query["MeasurementTypeID"]);

            int    pixels = int.Parse(query["pixels"]);
            string type   = query["type"] ?? "Average";

            DateTime startDate = DateTime.Parse(query["StartDate"]);
            DateTime endDate   = DateTime.Parse(query["EndDate"]);
            DateTime epoch     = new DateTime(1970, 1, 1);

            return(Task.Factory.StartNew(() =>
            {
                using (AdoDataConnection connection = new AdoDataConnection("systemSettings"))
                {
                    Stopwatch stopWatch = new Stopwatch();
                    stopWatch.Start();


                    string target = "PeriodicDataDisplay" + meterId.ToString() + measurementCharacteristicId.ToString() + startDate.Subtract(epoch).TotalMilliseconds.ToString() + endDate.Subtract(epoch).TotalMilliseconds.ToString() + type;
                    Dictionary <string, List <double[]> > data = (Dictionary <string, List <double[]> >)s_memoryCache.Get(target);
                    if (data == null)
                    {
                        data = new Dictionary <string, List <double[]> >();
                        IEnumerable <Channel> channels = (new TableOperations <Channel>(connection)).QueryRecordsWhere("MeterID = {0} AND MeasurementCharacteristicID = {1} AND MeasurementTypeID = {2}", meterId, measurementCharacteristicId, measurementTypeId);

                        string historianServer = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
                        string historianInstance = connection.ExecuteScalar <string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";

                        using (Historian historian = new Historian(historianServer, historianInstance))
                        {
                            foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(channels.Select(x => x.ID), startDate, endDate))
                            {
                                if (point.SeriesID.ToString() == type)
                                {
                                    Channel channel = channels.First(x => x.ID == point.ChannelID);
                                    if (!data.ContainsKey(channel.Name))
                                    {
                                        data.Add(channel.Name, new List <double[]>()
                                        {
                                            new[] { point.Timestamp.Subtract(epoch).TotalMilliseconds, point.Value }
                                        });
                                    }
                                    else
                                    {
                                        data[channel.Name].Add(new[] { point.Timestamp.Subtract(epoch).TotalMilliseconds, point.Value });
                                    }
                                }
                            }
                        }

                        s_memoryCache.Add(target, data, new CacheItemPolicy {
                            SlidingExpiration = TimeSpan.FromMinutes(0.5D)
                        });
                    }
                    Console.WriteLine(stopWatch.Elapsed);
                    return Downsample(data, pixels, new Range <DateTime>(startDate, endDate));
                }
            }, cancellationToken));
        }
    private List<List<TrendingDataLocation>> GetFramesFromHistorian(ContourQuery contourQuery)
    {
        DataTable idTable;
        string historianServer;
        string historianInstance;

        using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
        {
            string query =
                "SELECT " +
                "    Channel.ID AS ChannelID, " +
                "    Meter.ID AS MeterID, " +
                "    Meter.Name AS MeterName, " +
                "    MeterLocation.Latitude, " +
                "    MeterLocation.Longitude, " +
                "    Channel.PerUnitValue " +
                "FROM " +
                "    Meter JOIN " +
                "    MeterLocation ON Meter.MeterLocationID = MeterLocation.ID LEFT OUTER JOIN " +
                "    Channel ON " +
                "        Channel.MeterID = Meter.ID AND " +
                "        Channel.ID IN (SELECT ChannelID FROM ContourChannel WHERE ContourColorScaleName = {1}) " +
                "WHERE Meter.ID IN (SELECT * FROM authMeters({0}))";

            idTable = connection.RetrieveData(query, contourQuery.UserName, contourQuery.ColorScaleName);
            historianServer = connection.ExecuteScalar<string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
            historianInstance = connection.ExecuteScalar<string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";
        }

        if (!string.IsNullOrEmpty(contourQuery.Meters))
        {
            const int byteSize = 8;

            // Meter selections are stored as a base-64 string without padding, using '-' instead of '+' and '_' instead of '/'
            string padding = "A==".Remove(3 - (contourQuery.Meters.Length + 3) % 4);
            string base64 = contourQuery.Meters.Replace('-', '+').Replace('_', '/') + padding;
            byte[] meterSelections = Convert.FromBase64String(base64);

            // The resulting byte array is a simple set of bitflags ordered by meter ID and packed into the most significant bits.
            // In order to properly interpret the bytes, we must first group and order the data by meter ID to determine the location
            // of each meter's bitflag. Then we can filter out the unwanted data from the original table of IDs
            idTable.Select()
                .Select((Row, Index) => new { Row, Index })
                .GroupBy(obj => obj.Row.ConvertField<int>("MeterID"))
                .OrderBy(grouping => grouping.Key)
                .Where((grouping, index) => (meterSelections[index / byteSize] & (0x80 >> (index % byteSize))) == 0)
                .SelectMany(grouping => grouping)
                .OrderByDescending(obj => obj.Index)
                .ToList()
                .ForEach(obj => idTable.Rows.RemoveAt(obj.Index));
        }

        List<DataRow> meterRows = idTable
            .Select()
            .DistinctBy(row => row.ConvertField<int>("MeterID"))
            .ToList();

        DateTime startDate = contourQuery.GetStartDate();
        DateTime endDate = contourQuery.GetEndDate();
        int stepSize = contourQuery.StepSize;

        // The frames to be included are those whose timestamps fall
        // within the range which is specified by startDate and
        // endDate. We start by aligning startDate and endDate with
        // the nearest frame timestamps which fall within that range
        int startTimeOffset = (int)Math.Ceiling((startDate - startDate.Date).TotalMinutes / stepSize);
        startDate = startDate.Date.AddMinutes(startTimeOffset * stepSize);

        int endTimeOffset = (int)Math.Floor((endDate - endDate.Date).TotalMinutes / stepSize);
        endDate = endDate.Date.AddMinutes(endTimeOffset * stepSize);

        // Since each frame includes data from all timestamps between
        // the previous frame's timestamp and its own timestamp, we
        // must include one additional frame of data before startDate
        startDate = startDate.AddMinutes(-stepSize);

        int frameCount = (int)((endDate - startDate).TotalMinutes / stepSize);

        List<Dictionary<int, TrendingDataLocation>> frames = Enumerable.Repeat(meterRows, frameCount)
            .Select(rows => rows.Select(row => new TrendingDataLocation()
            {
                id = row.ConvertField<int>("MeterID"),
                name = row.ConvertField<string>("MeterName"),
                Latitude = row.ConvertField<double>("Latitude"),
                Longitude = row.ConvertField<double>("Longitude")
            }))
            .Select(locations => locations.ToDictionary(location => location.id))
            .ToList();

        Dictionary<int, double?> nominalLookup = idTable
            .Select("ChannelID IS NOT NULL")
            .ToDictionary(row => row.ConvertField<int>("ChannelID"), row => row.ConvertField<double?>("PerUnitValue"));

        Dictionary<int, List<TrendingDataLocation>> lookup = idTable
            .Select("ChannelID IS NOT NULL")
            .Select(row =>
            {
                int meterID = row.ConvertField<int>("MeterID");

                return new
                {
                    ChannelID = row.ConvertField<int>("ChannelID"),
                    Frames = frames.Select(locationLookup => locationLookup[meterID]).ToList()
                };
            })
            .ToDictionary(obj => obj.ChannelID, obj => obj.Frames);

        using (Historian historian = new Historian(historianServer, historianInstance))
        {
            foreach (TrendingDataPoint point in historian.Read(lookup.Keys, startDate, endDate))
            {
                List<TrendingDataLocation> locations = lookup[point.ChannelID];

                // Use ceiling to sort data into the next nearest frame.
                // Subtract 1 because startDate was shifted to include one additional frame of data
                int frameIndex = (int)Math.Ceiling((point.Timestamp - startDate).TotalMinutes / stepSize) - 1;

                if (frameIndex < 0 || frameIndex >= locations.Count)
                    continue;

                TrendingDataLocation frame = locations[frameIndex];

                double nominal = nominalLookup[point.ChannelID] ?? 1.0D;
                double value = point.Value / nominal;

                switch (point.SeriesID)
                {
                    case SeriesID.Minimum:
                        frame.Minimum = Math.Min(value, frame.Minimum ?? value);
                        break;

                    case SeriesID.Maximum:
                        frame.Maximum = Math.Max(value, frame.Maximum ?? value);
                        break;

                    case SeriesID.Average:
                        frame.Aggregate(value);
                        frame.Average = frame.GetAverage();
                        break;
                }
            }
        }

        return frames
            .Select(frame => frame.Values.ToList())
            .ToList();
    }
        private void ProcessMeasurement(Meter meter, PQMeasurement measurement, string historianServer, string historianInstance, DateTime startTime, DateTime endTime)
        {
            Channel     channel;
            PQTrendStat record;

            using (DataContext dataContext = new DataContext("systemSettings"))
            {
                channel = dataContext.Table <Channel>().QueryRecordWhere("MeasurementTypeID = {0} AND MeasurementCharacteristicID = {1} AND PhaseID = {2} AND HarmonicGroup = {3} AND MeterID = {4}", measurement.MeasurementTypeID, measurement.MeasurementCharacteristicID, measurement.PhaseID, measurement.HarmonicGroup, meter.ID);
                record  = dataContext.Table <PQTrendStat>().QueryRecordWhere("MeterID = {0} AND Date = {1} AND PQMeasurementTypeID = {2}", meter.ID, startTime, measurement.ID);
            }


            if (record == null)
            {
                record                     = new PQTrendStat();
                record.MeterID             = meter.ID;
                record.PQMeasurementTypeID = measurement.ID;
                record.Date                = startTime;
            }

            record.Max  = null;
            record.Min  = null;
            record.Avg  = null;
            record.CP99 = null;
            record.CP95 = null;
            record.CP05 = null;
            record.CP01 = null;

            if (channel != null)
            {
                using (Historian historian = new Historian(historianServer, historianInstance))
                {
                    IEnumerable <openHistorian.XDALink.TrendingDataPoint> data = historian.Read(new[] { channel.ID }, startTime, endTime).ToList();
                    if (!data.Any())
                    {
                        return;
                    }

                    IEnumerable <openHistorian.XDALink.TrendingDataPoint> avgList = data.Where(x => x.SeriesID == SeriesID.Average).OrderBy(x => x.Value);

                    try
                    {
                        record.Max = data.Where(x => x.SeriesID == SeriesID.Maximum).Select(x => x.Value).Max();
                        record.Min = data.Where(x => x.SeriesID == SeriesID.Minimum).Select(x => x.Value).Min();
                        record.Avg = avgList.Select(x => x.Value).Average();
                    }
                    catch (Exception ex)
                    {
                        if (PQTrendingWebReportSettings.Verbose)
                        {
                            Log.Error(ex.Message, ex);
                        }
                    }

                    try
                    {
                        int index99 = (int)(avgList.Count() * (0.995));
                        int index01 = (int)(avgList.Count() * (0.005));
                        record.CP99 = avgList.Where((x, i) => i >= index01 && i <= index99).Select(x => x.Value).Max();
                        record.CP01 = avgList.Where((x, i) => i >= index01 && i <= index99).Select(x => x.Value).Min();
                    }
                    catch (Exception ex)
                    {
                        record.CP99 = null;
                        record.CP01 = null;

                        if (PQTrendingWebReportSettings.Verbose)
                        {
                            Log.Error(ex.Message, ex);
                        }
                    }

                    try
                    {
                        int index95 = (int)(avgList.Count() * (0.975));
                        int index05 = (int)(avgList.Count() * (0.025));
                        record.CP95 = avgList.Where((x, i) => i >= index05 && i <= index95).Select(x => x.Value).Max();
                        record.CP05 = avgList.Where((x, i) => i >= index05 && i <= index95).Select(x => x.Value).Min();
                    }
                    catch (Exception ex)
                    {
                        record.CP95 = null;
                        record.CP05 = null;

                        if (PQTrendingWebReportSettings.Verbose)
                        {
                            Log.Error(ex.Message, ex);
                        }
                    }
                }

                using (DataContext dataContext = new DataContext("systemSettings"))
                {
                    if (record.Avg != null && record.Max != null && record.Min != null)
                    {
                        dataContext.Table <PQTrendStat>().AddNewOrUpdateRecord(record);
                    }
                }
            }
        }
    public TrendingDataSet getTrendsforChannelIDDate(string ChannelID, string targetDate)
    {
        //DateTime epoch = new DateTime(1970, 1, 1);
        //string theSproc = "dbo.selectTrendingDataByChannelIDDate2";
        //DataSet dataSet = new DataSet();
        //TrendingDataSet trendingDataSet = new TrendingDataSet();

        //using (SqlConnection connection = new SqlConnection(connectionstring))
        //using (SqlCommand command = connection.CreateCommand())
        //using (SqlDataAdapter adapter = new SqlDataAdapter(command))
        //{
        //    command.CommandText = theSproc;
        //    command.CommandType = CommandType.StoredProcedure;
        //    command.Parameters.AddWithValue("@EventDate", targetDate);
        //    command.Parameters.AddWithValue("@ChannelID", ChannelID);
        //    command.CommandTimeout = 300;

        //    connection.Open();
        //    adapter.Fill(dataSet);

        //    trendingDataSet.ChannelData = dataSet.Tables[0].Rows
        //        .Cast<DataRow>()
        //        .Select(row => new TrendingDataPoint()
        //        {
        //            Time = row.Field<DateTime>("thedate").Subtract(epoch).TotalMilliseconds,
        //            Maximum = row.Field<double>("themaximum"),
        //            Minimum = row.Field<double>("theminimum"),
        //            Average = row.Field<double>("theaverage")
        //        })
        //        .ToArray();

        //    trendingDataSet.AlarmLimits = dataSet.Tables[1].Rows
        //        .Cast<DataRow>()
        //        .Select(row => new TrendingAlarmLimit()
        //        {
        //            TimeStart = row.Field<DateTime>("thedatefrom").Subtract(epoch).TotalMilliseconds,
        //            TimeEnd = row.Field<DateTime>("thedateto").Subtract(epoch).TotalMilliseconds,
        //            High = row.Field<double?>("alarmlimithigh"),
        //            Low = row.Field<double?>("alarmlimitlow")
        //        })
        //        .ToArray();

        //    trendingDataSet.OffNormalLimits = dataSet.Tables[2].Rows
        //        .Cast<DataRow>()
        //        .Select(row => new TrendingAlarmLimit()
        //        {
        //            TimeStart = row.Field<DateTime>("thedatefrom").Subtract(epoch).TotalMilliseconds,
        //            TimeEnd = row.Field<DateTime>("thedateto").Subtract(epoch).TotalMilliseconds,
        //            High = row.Field<double?>("offlimithigh"),
        //            Low = row.Field<double?>("offlimitlow")
        //        })
        //        .ToArray();
        //}
        string historianServer;
        string historianInstance;
        IEnumerable<int> channelIDs = new List<int>() { Convert.ToInt32(ChannelID) };
        DateTime startDate = Convert.ToDateTime(targetDate);
        DateTime endDate = startDate.AddDays(1);
        TrendingDataSet trendingDataSet = new TrendingDataSet();
        DateTime epoch = new DateTime(1970, 1, 1);

        using (AdoDataConnection connection = new AdoDataConnection(connectionstring, typeof(SqlConnection), typeof(SqlDataAdapter)))
        {
            historianServer = connection.ExecuteScalar<string>("SELECT Value FROM Setting WHERE Name = 'Historian.Server'") ?? "127.0.0.1";
            historianInstance = connection.ExecuteScalar<string>("SELECT Value FROM Setting WHERE Name = 'Historian.Instance'") ?? "XDA";

            using (Historian historian = new Historian(historianServer, historianInstance))
            {
                foreach (openHistorian.XDALink.TrendingDataPoint point in historian.Read(channelIDs, startDate, endDate))
                {
                    if (!trendingDataSet.ChannelData.Exists(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds))
                    {
                        trendingDataSet.ChannelData.Add(new TrendingDataDatum());
                        trendingDataSet.ChannelData[trendingDataSet.ChannelData.Count - 1].Time = point.Timestamp.Subtract(epoch).TotalMilliseconds;
                    }

                    if (point.SeriesID.ToString() == "Average")
                        trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Average = point.Value;
                    else if (point.SeriesID.ToString() == "Minimum")
                        trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Minimum = point.Value;
                    else if (point.SeriesID.ToString() == "Maximum")
                        trendingDataSet.ChannelData[trendingDataSet.ChannelData.IndexOf(x => x.Time == point.Timestamp.Subtract(epoch).TotalMilliseconds)].Maximum = point.Value;

                }
            }
            IEnumerable<DataRow> table = Enumerable.Empty<DataRow>();

            table = connection.RetrieveData(" Select {0} AS thedatefrom, " +
                                                        "        DATEADD(DAY, 1, {0}) AS thedateto, " +
                                                        "        CASE WHEN AlarmRangeLimit.PerUnit <> 0 AND Channel.PerUnitValue IS NOT NULL THEN AlarmRangeLimit.High * PerUnitValue ELSE AlarmRangeLimit.High END AS alarmlimithigh," +
                                                        "        CASE WHEN AlarmRangeLimit.PerUnit <> 0 AND Channel.PerUnitValue IS NOT NULL THEN AlarmRangeLimit.Low * PerUnitValue ELSE AlarmRangeLimit.Low END AS alarmlimitlow " +
                                                        " FROM   AlarmRangeLimit JOIN " +
                                                        "        Channel ON AlarmRangeLimit.ChannelID = Channel.ID " +
                                                        "WHERE   AlarmRangeLimit.AlarmTypeID = (SELECT ID FROM AlarmType where Name = 'Alarm') AND " +
                                                        "        AlarmRangeLimit.ChannelID = {1}", startDate, Convert.ToInt32(ChannelID)).Select();

            foreach (DataRow row in table)
            {
                trendingDataSet.AlarmLimits.Add(new TrendingAlarmLimit() { High = row.Field<double?>("alarmlimithigh"), Low = row.Field<double?>("alarmlimitlow"), TimeEnd = row.Field<DateTime>("thedateto").Subtract(epoch).TotalMilliseconds, TimeStart = row.Field<DateTime>("thedatefrom").Subtract(epoch).TotalMilliseconds });
            }

            table = Enumerable.Empty<DataRow>();

            table = connection.RetrieveData(" DECLARE @dayOfWeek INT = DATEPART(DW, {0}) - 1 " +
                                                        " DECLARE @hourOfWeek INT = @dayOfWeek * 24 " +
                                                        " ; WITH HourlyIndex AS" +
                                                        " ( " +
                                                        "   SELECT @hourOfWeek AS HourOfWeek " +
                                                        "   UNION ALL " +
                                                        "   SELECT HourOfWeek + 1 " +
                                                        "   FROM HourlyIndex" +
                                                        "   WHERE (HourOfWeek + 1) < @hourOfWeek + 24" +
                                                        " ) " +
                                                        " SELECT " +
                                                        "        DATEADD(HOUR, HourlyIndex.HourOfWeek - @hourOfWeek, {0}) AS thedatefrom, " +
                                                        "        DATEADD(HOUR, HourlyIndex.HourOfWeek - @hourOfWeek + 1, {0}) AS thedateto, " +
                                                        "        HourOfWeekLimit.High AS offlimithigh, " +
                                                        "        HourOfWeekLimit.Low AS offlimitlow " +
                                                        " FROM " +
                                                        "        HourlyIndex LEFT OUTER JOIN " +
                                                        "        HourOfWeekLimit ON HourOfWeekLimit.HourOfWeek = HourlyIndex.HourOfWeek " +
                                                        " WHERE " +
                                                        "        HourOfWeekLimit.ChannelID IS NULL OR " +
                                                        "        HourOfWeekLimit.ChannelID = {1} ", startDate, Convert.ToInt32(ChannelID)).Select();

            foreach (DataRow row in table)
            {
                trendingDataSet.OffNormalLimits.Add(new TrendingAlarmLimit() { High = row.Field<double?>("offlimithigh"), Low = row.Field<double?>("offlimitlow"), TimeEnd = row.Field<DateTime>("thedateto").Subtract(epoch).TotalMilliseconds, TimeStart = row.Field<DateTime>("thedatefrom").Subtract(epoch).TotalMilliseconds });
            }

        }

        return trendingDataSet;
    }
Ejemplo n.º 18
0
        private void ProcessMeasurement(Meter meter, StepChangeMeasurement measurement, string historianServer, string historianInstance, DateTime startTime, DateTime endTime)
        {
            using (DataContext dataContext = new DataContext("systemSettings"))
                using (Historian historian = new Historian(historianServer, historianInstance))
                {
                    PQMeasurement  pqMeasurement = dataContext.Table <PQMeasurement>().QueryRecordWhere("ID = {0}", measurement.PQMeasurementID);
                    Channel        channel       = dataContext.Table <Channel>().QueryRecordWhere("MeasurementTypeID = {0} AND MeasurementCharacteristicID = {1} AND PhaseID = {2} AND HarmonicGroup = {3} AND MeterID = {4}", pqMeasurement.MeasurementTypeID, pqMeasurement.MeasurementCharacteristicID, pqMeasurement.PhaseID, pqMeasurement.HarmonicGroup, meter.ID);
                    StepChangeStat record        = dataContext.Table <StepChangeStat>().QueryRecordWhere("MeterID = {0} AND Date = {1} AND StepChangeMeasurementID = {2}", meter.ID, startTime, measurement.ID);
                    Unit           unit          = dataContext.Table <Unit>().QueryRecordWhere("ID = {0}", pqMeasurement.UnitID);

                    if (record == null)
                    {
                        record         = new StepChangeStat();
                        record.MeterID = meter.ID;
                        record.StepchangeMeasurementID = measurement.ID;
                        record.Date = startTime;
                    }

                    record.Value = 0;

                    if (channel != null)
                    {
                        IEnumerable <openHistorian.XDALink.TrendingDataPoint> data = historian.Read(new[] { channel.ID }, startTime.AddHours(-1), endTime).Where(x => x.SeriesID == SeriesID.Average).ToList();

                        // no associated data for this measurement;  just return without creating the record.
                        if (!data.Any())
                        {
                            return;
                        }

                        try
                        {
                            foreach (openHistorian.XDALink.TrendingDataPoint point in data)
                            {
                                if (point.Timestamp >= startTime)
                                {
                                    double lastHourAvg = data.Where(x => x.Timestamp >= point.Timestamp.AddHours(-1) && x.Timestamp < point.Timestamp).Select(x => x.Value).Average();

                                    double std     = data.StandardDeviation(x => x.Value);
                                    double average = data.Average(x => x.Value);

                                    // if value is outside 5 sigma, do not check for step change
                                    if (point.Value > average + std * 5 || point.Value < average - std * 5)
                                    {
                                        continue;
                                    }

                                    if (unit.Name == "Percent")
                                    {
                                        if (Math.Abs(point.Value - lastHourAvg) > measurement.Setting)
                                        {
                                            record.Value++;
                                        }
                                    }
                                    else
                                    {
                                        if ((Math.Abs(point.Value - lastHourAvg) * 100 / lastHourAvg) > measurement.Setting)
                                        {
                                            record.Value++;
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception)
                        {
                            // no associated data for this measurement;  just return without creating the record.
                            return;
                        }
                    }

                    if (record.Value > 0)
                    {
                        dataContext.Table <StepChangeStat>().AddNewOrUpdateRecord(record);
                    }
                }
        }