Example #1
0
        private AFAttributeList LoadParameters()
        {
            if (Attribute == null || Attribute.Element == null) {
                throw new ApplicationException("Attribute and/or element is null");
            }

            var paramAttributes = new AFAttributeList();

            if (!string.IsNullOrEmpty(fPointAttribute)) {
                AFDatabase db = Attribute.Database;
                if (db == null) {
                    throw new ApplicationException("No database found");
                }

                // find Attribute's object by it name from parameters
                var ptAttr = AFAttribute.FindAttribute(fPointAttribute, Attribute);
                if (ptAttr == null) {
                    throw new ApplicationException(string.Format(Resources.ERR_AttributeHasNotBeenFound, fPointAttribute));
                }

                paramAttributes.Add(ptAttr);
            } else {
                throw new ApplicationException("Name of PI Point attribute is null or empty");
            }

            return paramAttributes;
        }
Example #2
0
        public void Run()
        {
            AFElement element = AFObject.FindObject(@"\\BSHANGE6430s\Sandbox\Reactive") as AFElement;
            AFAttributeList attrList = new AFAttributeList(element.Attributes);

            AFDataPipe dataPipe = new AFDataPipe();
            var errors = dataPipe.AddSignups(attrList);

            IObservable<AFDataPipeEvent> obsDataPipe = dataPipe.CreateObservable();

            IObservable<AFDataPipeEvent> sinusoidSnapshot = obsDataPipe
                .Where(evt => evt.Value.Attribute.Name == "SINUSOID" && evt.Action == AFDataPipeAction.Add);

            IObservable<AFDataPipeEvent> cdt158Snapshot = obsDataPipe
                .Where(evt => evt.Value.Attribute.Name == "CDT158" && evt.Action == AFDataPipeAction.Add);

            IObservable<AFDataPipeEvent> sumStream = sinusoidSnapshot.Add(cdt158Snapshot);

            IDisposable subscription = sumStream.Subscribe(evt =>
            {
                Console.WriteLine("Timestamp: {0}, SINUSOID + CDT158: {1}", evt.Value.Timestamp.ToString("HH:mm:ss.ffff"), evt.Value.Value);
            });

            Console.WriteLine("Press any key to unsubscribe");
            Console.ReadKey();

            subscription.Dispose();
            dataPipe.Dispose();
        }
Example #3
0
 public AFDataObserver(AFAttributeList attrList, ProcessAFDataPipeEventDelegate processEvent, int pollInterval = 5000)
 {
     AttributeList = attrList;
     DataPipe      = new AFDataPipe();
     _threadSleepTimeInMilliseconds = pollInterval;
     _processEvent = processEvent;
 }
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            // I could not find a free API that supports historial data. so I'm just getting newest forecast data
            AFValue result = new AFValue();

            using (var webClient = new WebClient())
            {
                // API only gives me access from a browser, so we need to identify as a browser
                webClient.Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
                webClient.Headers["Accept"]     = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8";

                var url  = new Uri($"{weatherBaseUrl}{Lat},{Lng}/forecast");
                var json = webClient.DownloadString(url);
                var j    = JObject.Parse(json);

                var results = j["properties"]["periods"].Select(sf => (JObject)sf).Select(sf =>
                                                                                          new WeatherForecastPeriod()
                {
                    Temperature     = sf["temperature"].Value <int>(),
                    TemperatureUnit = sf["temperatureUnit"].Value <string>(),
                    StartTime       = sf["startTime"].Value <DateTime>(),
                    EndTime         = sf["endTime"].Value <DateTime>()
                });
                result.Value = results.First().Temperature;
                result.UOM   = this.PISystem.UOMDatabase.UOMs.First(x => x.Abbreviation == $"°{results.First().TemperatureUnit}");
            }
            return(result);
        }
        public static async Task<IList<IDictionary<AFSummaryTypes, AFValue>>> GetSummariesAsync(AFAttributeList attributeList)
        {
            Console.WriteLine("Calling GetSummariesAsync\n");

            Task<IDictionary<AFSummaryTypes, AFValue>>[] tasks = attributeList
                // Do not make the call if async is not supported
                .Where(attr => (attr.SupportedDataMethods & AFDataMethods.Asynchronous) == AFDataMethods.Asynchronous)
                .Select(async attr =>
                {
                    try
                    {
                        AFSummaryTypes mySummaries = AFSummaryTypes.Minimum | AFSummaryTypes.Maximum | AFSummaryTypes.Average | AFSummaryTypes.Total;
                        AFTimeRange timeRange = new AFTimeRange(new AFTime("*-1d"), new AFTime("*"));
                    
                        return await attr.Data.SummaryAsync(
                            timeRange: timeRange,
                            summaryType: mySummaries,
                            calculationBasis: AFCalculationBasis.TimeWeighted,
                            timeType: AFTimestampCalculation.Auto);
                    }
                    catch (AggregateException ae)
                    {
                        Console.WriteLine("{0}: {1}", attr.Name, ae.Flatten().InnerException.Message);
                        return null;
                    }
                })
                .ToArray();

            return await Task.WhenAll(tasks);
        }
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            if (!fChecked)
            {
                CheckConfig();
            }

            try {
                AFTime time;
                if (timeContext is AFTime)
                {
                    time = (AFTime)timeContext;
                }
                else if (timeContext is AFTimeRange)
                {
                    var timeRange = (AFTimeRange)timeContext;
                    time = (Attribute.Element is AFEventFrame) ? timeRange.StartTime : timeRange.EndTime;
                }
                else
                {
                    time = AFTime.NowInWholeSeconds;
                }

                AFValue result = Calculate(time, inputAttributes, inputValues);
                return(result);
            } catch (Exception) {
                UnloadParameters();
                fChecked = false;
                throw;
            }
        }
Example #7
0
        private AFAttributeList GetAttributes()
        {
            int startIndex = 0;
            int totalCount;
            int pageSize = 1000;

            AFAttributeList attrList = new AFAttributeList();

            do
            {
                AFAttributeList attrListTemp = AFAttribute.FindElementAttributes(
                    database: AttributeTemplate.Database,
                    searchRoot: null,
                    nameFilter: "*",
                    elemCategory: null,
                    elemTemplate: AttributeTemplate.ElementTemplate,
                    elemType: AFElementType.Any,
                    attrNameFilter: AttributeTemplate.Name,
                    attrCategory: null,
                    attrType: TypeCode.Empty,
                    searchFullHierarchy: true,
                    sortField: AFSortField.Name,
                    sortOrder: AFSortOrder.Ascending,
                    startIndex: startIndex,
                    maxCount: pageSize,
                    totalCount: out totalCount);

                attrList.AddRange(attrListTemp);

                startIndex += pageSize;
            } while (startIndex < totalCount);

            return(attrList);
        }
Example #8
0
        static void Main(string[] args)
        {
            AFDatabase db = ConnectionHelper.GetDatabase("PISRV01", "Feeder Voltage Monitoring");

            AFAttributeList attrList = GetAttributes(db);

            try
            {
                Task <IList <IDictionary <AFSummaryTypes, AFValue> > > summariesTask = AFAsyncDataReader.GetSummariesAsync(attrList);

                // Wait for the summaries result
                IList <IDictionary <AFSummaryTypes, AFValue> > summaries = summariesTask.Result;
                foreach (var summary in summaries)
                {
                    WriteSummaryItem(summary);
                }
            }
            catch (AggregateException ae)
            {
                Console.WriteLine("{0}", ae.Flatten().InnerException.Message);
            }

            Console.WriteLine("Press any key to quit");
            Console.ReadKey();
        }
        public void Start()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("AssetRankProvider was disposed.");
            }

            // Gets all attributes from the AttributeTemplate
            AFAttributeList attrList = GetAttributes();

            Console.WriteLine("{0} | Signing up for updates for {1} attributes", DateTime.Now, attrList.Count);
            DataPipe.Subscribe(this);

            // Throw exception on errors
            AFListResults <AFAttribute, AFDataPipeEvent> initEvents = DataPipe.AddSignupsWithInitEvents(attrList);

            if (initEvents.HasErrors)
            {
                throw new Exception("There was an error during signup.", new AggregateException(initEvents.Errors.Values));
            }

            // Initialize the dictionary cache
            foreach (AFDataPipeEvent dpEvent in initEvents)
            {
                OnNext(dpEvent);
            }

            Console.WriteLine("{0} | Signed up for updates for {1} attributes\n", DateTime.Now, attrList.Count);

            _mainTask = Task.Run(() =>
            {
                bool hasMoreEvents = false;

                while (true)
                {
                    if (_ct.IsCancellationRequested)
                    {
                        // The main task in AssetRankProvider is cancelled.
                        _ct.ThrowIfCancellationRequested();
                        // NOTE!!! A "OperationCanceledException was unhandled
                        // by user code" error will be raised here if "Just My Code"
                        // is enabled on your computer. On Express editions JMC is
                        // enabled and cannot be disabled. The exception is benign.
                        // Just press F5 to continue executing your code.
                    }

                    AFErrors <AFAttribute> results = DataPipe.GetObserverEvents(out hasMoreEvents);

                    if (results != null)
                    {
                        Console.WriteLine("Errors in GetObserverEvents: {0}", results.ToString());
                    }

                    if (!hasMoreEvents)
                    {
                        Thread.Sleep(_threadSleepTimeInMilliseconds);
                    }
                }
            }, _ct);
        }
        public override AFAttributeList GetInputs(object context)
        {
            // Loop through the config string, looking for attributes
            // The Config string is semicolon separated list of attributes and strings
            // Strings must be enclosed in " "
            // Will also handle standard AF substitions (%ELEMENT%, %TIME%, etc.)
            AFAttributeList paramAttributes = null;

            string[] subStrings = ConfigString.Split(';');

            string s     = subStrings[0].Trim();
            String subst = SubstituteParameters(s, this, context, null);

            if (!String.IsNullOrEmpty(subst))
            {
                // Get attribute will resolve attribute references
                AFAttribute attr = GetAttribute(subst);
                if (attr == null || attr.IsDeleted)
                {
                    throw new ApplicationException(String.Format("Unknown attribute '{0}'", s));
                }
                if (paramAttributes == null)
                {
                    paramAttributes = new AFAttributeList();
                }
                paramAttributes.Add(attr);
            }

            return(paramAttributes);
        }
        private static AFAttributeList GetAttributes(AFDatabase database)
        {
            int startIndex = 0;
            int pageSize = 1000;
            int totalCount;

            AFAttributeList attrList = new AFAttributeList();

            do
            {
                AFAttributeList results = AFAttribute.FindElementAttributes(
                     database: database,
                     searchRoot: null,
                     nameFilter: null,
                     elemCategory: null,
                     elemTemplate: database.ElementTemplates["Feeder"],
                     elemType: AFElementType.Any,
                     attrNameFilter: "Power",
                     attrCategory: null,
                     attrType: TypeCode.Empty,
                     searchFullHierarchy: true,
                     sortField: AFSortField.Name,
                     sortOrder: AFSortOrder.Ascending,
                     startIndex: startIndex,
                     maxCount: pageSize,
                     totalCount: out totalCount);

                attrList.AddRange(results);

                startIndex += pageSize;
            } while (startIndex < totalCount);

            return attrList;
        }
        static AFAttributeList GetAttributes(AFDatabase database)
        {
            int startIndex = 0;
            int pageSize   = 1000;
            int totalCount;

            AFAttributeList attrList = new AFAttributeList();

            do
            {
                AFAttributeList results = AFAttribute.FindElementAttributes(
                    database: database,
                    searchRoot: null,
                    nameFilter: null,
                    elemCategory: null,
                    elemTemplate: database.ElementTemplates["MeterBasic"],
                    elemType: AFElementType.Any,
                    attrNameFilter: "Energy Usage",
                    attrCategory: null,
                    attrType: TypeCode.Empty,
                    searchFullHierarchy: true,
                    sortField: AFSortField.Name,
                    sortOrder: AFSortOrder.Ascending,
                    startIndex: startIndex,
                    maxCount: pageSize,
                    totalCount: out totalCount);

                attrList.AddRange(results);

                startIndex += pageSize;
            } while (startIndex < totalCount);

            return(attrList);
        }
Example #13
0
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            if (!fChecked)
            {
                CheckConfig();
            }

            try {
                // Note that timeContext is an object.
                // We need to examine it further in order to resolve it to an AFTime.
                AFTime time;
                if (timeContext is AFTime)
                {
                    time = (AFTime)timeContext;
                }
                else if (timeContext is AFTimeRange)
                {
                    var timeRange = (AFTimeRange)timeContext;
                    time = (Attribute.Element is AFEventFrame) ? timeRange.StartTime : timeRange.EndTime;
                }
                else
                {
                    time = AFTime.NowInWholeSeconds;
                }

                // Important to note that the order of inputValues matches the order of inputAttributes.
                AFValue result = Calculate(time, inputAttributes, inputValues);
                return(result);
            } catch (Exception) {
                UnloadParameters();
                throw;
            }
        }
        public void Run()
        {
            PISystems piSystems = new PISystems();
            PISystem piSystem = piSystems["<AFSERVER>"];

            AFDatabase afDatabase = piSystem.Databases["NuGreen"];

            AFElementTemplate boilerTemplate = afDatabase.ElementTemplates["Boiler"];

            const int pageSize = 1000;
            int startIndex = 0;
            int totalCount;
            do
            {
                // Find a collection of elements instantiated from the Boiler tempplate.
                // Only the Elements' header information (Name, Description, Template, Type, etc.)
                // are loaded from the AF Server by this call.
                AFNamedCollection<AFElement> elements = AFElement.FindElements(
                    database: afDatabase,
                    searchRoot: null,
                    query: "Boiler",
                    field: AFSearchField.Template,
                    searchFullHierarchy: true,
                    sortField: AFSortField.Name,
                    sortOrder: AFSortOrder.Ascending,
                    startIndex: startIndex,
                    maxCount: pageSize,
                    totalCount: out totalCount);
                if (elements == null) break;

                // Partially load the element by retrieving information only for the Water Flow attribute.
                AFElement.LoadAttributes(elements, new[] { boilerTemplate.AttributeTemplates["Water Flow"] });

                Console.WriteLine("Found {0} Elements.", elements.Count);

                AFAttributeList attrList = new AFAttributeList();

                // Because we are retrieving the Water Flow attribute which was previously loaded,
                // no additional server calls are made.
                // If LoadAttributes had not been called previously, then a server call would have been made for each element
                // in the loop below.
                foreach (AFElement item in elements)
                {
                    attrList.Add(item.Attributes["Water Flow"]);
                }

                AFValues values = attrList.GetValue();

                Console.WriteLine("  Water Flow values");
                foreach (AFValue val in values)
                {
                    Console.WriteLine("  Element: {0}, Timestamp: {1}, Value: {2}",
                        val.Attribute.Element, val.Timestamp, val.Value.ToString());
                }

                startIndex += pageSize;

            } while (startIndex < totalCount);
        }
Example #15
0
        static void PrintDailyAverageEnergyUsage(AFDatabase database, string startTime, string endTime)
        {
            Console.WriteLine(string.Format("Print Daily Energy Usage - Start: {0}, End: {1}", startTime, endTime));
            AFAttributeList attrList = new AFAttributeList();

            // Use this method if you get stuck trying to find attributes
            // attrList = GetAttributes();
        }
        public static async Task<IList<IDictionary<AFSummaryTypes, AFValue>>> GetSummariesAsync(AFAttributeList attributeList)
        {
            Console.WriteLine("Calling GetSummariesAsync");

            // Your code here

            // Change the return from null
            return null;
        }
        public void PrintEnergyUsageAtTime(string timeStamp)
        {
            AFAttributeList attrList = new AFAttributeList();

            // Use this method if you get stuck trying to find attributes
            // attrList = GetAttribute();

            // Your code here
        }
 public override AFAttributeList GetInputs(object context)
 {
     if (DateTime.UtcNow.Subtract(fLastLoadAttribute).Seconds > 10 || fParamAttributes == null)
     {
         fParamAttributes = null;
         LoadParameters();
     }
     return(fParamAttributes);
 }
        public void PrintDailyAverageEnergyUsage(string startTime, string endTime)
        {
            AFAttributeList attrList = new AFAttributeList();

            // Use this method if you get stuck trying to find attributes
            // attrList = GetAttribute();

            // Your code here
        }
Example #20
0
        private AFValue Calculate(AFTime time, AFAttributeList inputAttributes, AFValues inputValues)
        {
            if (time == null)
            {
                throw new ArgumentException("No timestamp");
            }

            if (inputAttributes == null || inputAttributes.Count == 0)
            {
                throw new ArgumentException("No input attributes");
            }

            if (inputValues == null || inputValues.Count == 0)
            {
                throw new ArgumentException(Resources.ERR_NoInputValues);
            }

            AFValue inVal;

            if (inputAttributes.Count > 0)
            {
                inVal = inputAttributes[0].GetValue(time);

                if (inVal == null)
                {
                    throw new ApplicationException("Input value is null");
                }
                else
                {
                    AFEnumerationValue enumValue = inVal.Value as AFEnumerationValue;
                    if (enumValue != null && enumValue.Value == 248)
                    {
                        // Attempting to handle an error when the output value is 248 instead of the NoData state
                        return(AFValue.CreateSystemStateValue(this.Attribute, AFSystemStateCode.NoData, time));
                    }
                    else
                    {
                        double keyValue    = (double)inVal.Value;
                        double resultValue = GetCalibratedValue(keyValue);

                        if (!double.IsNaN(resultValue))
                        {
                            return(new AFValue(this.Attribute, resultValue, inVal.Timestamp, this.Attribute.DefaultUOM));
                        }
                        else
                        {
                            return(AFValue.CreateSystemStateValue(this.Attribute, AFSystemStateCode.NoData, time));
                        }
                    }
                }
            }
            else
            {
                throw new ApplicationException(string.Format("Input attribute not found (#{0}", 1));
            }
        }
        // ===================================================================================
        // Override the Various Inputs required to calculate a value for this attribute.
        // ===================================================================================
        public override AFAttributeList GetInputs(object context)
        {
            AFAttributeList inputs = new AFAttributeList();

            //// TODO add better error handling here.
            inputs.Add(this.GetAttribute(_targetAttributeName));
            LoadParameters();
            //// Anytime someone asks for values from this data reference we tell the SDK that we also need these attributes.
            return(inputs);
        }
Example #22
0
        public void Start()
        {
            // Gets all attributes from the AttributeTemplate
            AFAttributeList attrList = GetAttributes();

            // Your code here
            // 1. Subscribe this instance to the data pipe.
            // 2. Signup the attributes in attrList above to the data pipe.
            // 3. Start polling for data pipe events.
        }
Example #23
0
        static void PrintEnergyUsageAtTime(AFDatabase database, string timeStamp)
        {
            Console.WriteLine("Print Energy Usage at Time: {0}", timeStamp);
            AFAttributeList attrList = new AFAttributeList();

            // Use this method if you get stuck trying to find attributes
            // attrList = GetAttributes();

            // Your code here
        }
        private AFAttributeList CreateBrandNewInputList(object context)
        {
            // PRO TIP:
            // See comments in GetInputs where you want to avoid _cachedInputAttrs.Add or AddRange.
            // For thread safety, use a brand new list that is local to this method.

            // Start with a brand new list
            var brandNewList = new AFAttributeList();

            AFAttribute measurement = null;

            // First and foremost we need a measurement attribute, which is the centerpoint to compare against limits.
            if (UseParentAttribute)
            {
                // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/P_OSIsoft_AF_Asset_AFDataReference_Attribute.htm
                // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/P_OSIsoft_AF_Asset_AFAttribute_Parent.htm
                measurement = Attribute.Parent;
                if (measurement == null)
                {
                    throw new Exception("Root-level attribute does not have a parent.  You must define 'MeasAttr=something' in the ConfigString.");
                }
            }
            else
            {
                // Let's offer some bit of name substitution.
                // However, the GetInputs method lacks any timeContext, which restricts @value substitution
                // to current values only.  This restriction is fine for static attributes.
                // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/T_OSIsoft_AF_AFNameSubstitutionType.htm
                var path = SubstituteParameters(_measAttrName, this, context, timeContext: null);
                // Note that the final fetch of the measurement attribute is *relative* to the current Attribute.
                // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/P_OSIsoft_AF_Asset_AFAttribute_Attributes.htm
                measurement = Attribute.Attributes[path];
                if (measurement == null)
                {
                    throw new Exception($"MeasAttr '{_measAttrName}' not found.  Check your ConfigString.");
                }
            }

            if (!IsNumericType(Type.GetTypeCode(measurement.Type)))
            {
                throw new Exception($"MeasAttr does not have a numeric Type.");
            }

            // If the list will have any items, the measurement will always be at Index 0.
            brandNewList.Add(measurement);

            // Let the CDR automatically fetch the associated limits.
            // These could come back in any order, plus some or all may be missing!
            // Geez, doesn't that make it fun and challenging!
            // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/M_OSIsoft_AF_Asset_AFAttribute_GetAttributesByTrait.htm
            brandNewList.AddRange(measurement.GetAttributesByTrait(AllowedTraits));

            return(brandNewList);
        }
Example #25
0
        public override AFAttributeList GetInputs(object context)
        {
            AFAttributeList attList = new AFAttributeList();

            attList.Add(this.Attribute.Element.Attributes["Latitude"]);
            attList.Add(this.Attribute.Element.Attributes["Longitude"]);

            _uomMeter = Attribute.PISystem.UOMDatabase.UOMs["meter"];
            _uomMPH   = Attribute.PISystem.UOMDatabase.UOMs["mile per hour"];

            return(attList);
        }
Example #26
0
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            if (!fChecked)
            {
                CheckConfig();
            }

            try {
                AFTime time;
                if (timeContext is AFTime)
                {
                    time = (AFTime)timeContext;
                }
                else if (timeContext is AFTimeRange)
                {
                    var timeRange = (AFTimeRange)timeContext;
                    time = (Attribute.Element is AFEventFrame) ? timeRange.StartTime : timeRange.EndTime;
                }
                else
                {
                    time = AFTime.NowInWholeSeconds;
                }

                string timeOffset = string.IsNullOrEmpty(fTimeOffset) ? "*" : fTimeOffset;

                int result = 0;
                try {
                    var fileInfo = new FileInfo(fFilePath);
                    if (fileInfo.Length != 0)
                    {
                        // exists
                        if (timeOffset == "*")
                        {
                            result = 1;
                        }
                        else
                        {
                            AFTime xtime = AFTime.Parse(timeOffset);
                            result = (fileInfo.LastWriteTime >= xtime.LocalTime) ? 2 : 1;
                        }
                    }
                } catch (FileNotFoundException ex) {
                    result = -1;
                }

                return(new AFValue(base.Attribute, result, time, Attribute.DefaultUOM));
            } catch (Exception) {
                UnloadParameters();
                fChecked = false;
                throw;
            }
        }
        public static void PrintEnergyUsageAtTime(AFDatabase database, string timeStamp)
        {
            Console.WriteLine("Print Energy Usage at Time: {0}", timeStamp);

            AFAttributeList attrList = GetAttributes(database, "MeterBasic", "Energy Usage");
            AFTime          time     = new AFTime(timeStamp);
            IList <AFValue> vals     = attrList.Data.RecordedValue(time);

            foreach (AFValue val in vals)
            {
                Console.WriteLine("Meter: {0}, Timestamp (Local): {1:yyyy-MM-dd HH\\h}, Value: {2:0.00} {3}", val.Attribute.Element.Name, val.Timestamp.LocalTime, val.Value, val.UOM?.Abbreviation);
            }

            Console.WriteLine();
        }
Example #28
0
        private AFAttributeList LoadParameters()
        {
            if (Attribute == null || Attribute.Element == null)
            {
                throw new ApplicationException("Attribute and/or element is null");
            }

            var paramAttributes = new AFAttributeList();

            if (!string.IsNullOrEmpty(fFilePath) || !string.IsNullOrEmpty(fTimeOffset))
            {
            }

            return(paramAttributes);
        }
Example #29
0
        //Gets the input Attributes
        public override AFAttributeList GetInputs(object context)
        {
            AFAttributeList inputs = new AFAttributeList();

            if (!String.IsNullOrEmpty(latAttribute))
            {
                inputs.Add(this.GetAttribute(latAttribute)); //Adds the Latitude Attribute to the input attribute colletion
            }

            if (!String.IsNullOrEmpty(longAttribute))
            {
                inputs.Add(this.GetAttribute(longAttribute)); //Adds the Longitude Attribute to the input attribute colletion
            }

            return(inputs);
        }
Example #30
0
        /// <summary>
        /// Set AF Attribute's ConfigString based on existing PI points
        /// </summary>
        /// <param name="attributes"></param>
        private static void SetConfigStrings(IList <AFAttribute> attributes)
        {
            AFAttributeList attrList = new AFAttributeList(attributes);
            var             points   = attrList.GetPIPoint();

            IList <string> configStrings = new List <string>(attrList.Count);

            foreach (var attrPoint in points.Results)
            {
                AFAttribute attribute    = attrPoint.Key;
                string      configString = attrPoint.Value.GetPath(AFEncodeType.NameThenID).Replace(";{", "?").Replace("}", "").Replace(";?", "?");
                configStrings.Add(configString);
            }

            AFAttribute.SetConfigStrings(attrList, configStrings);
        }
Example #31
0
        //calculate value of attribute
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            string[] splitConfig    = ConfigString.Split(';');
            string   selectedOption = splitConfig[2];

            if (selectedOption == "convertRadio")
            {
                return(PLCTimeConvert(inputValues[0], splitConfig[0]));
            }
            else //selectedOption == "formatRadio"
            {
                AFValue dateVal = inputValues[0];
                AFValue timeVal = inputValues[1];
                return(PLCTimeFormatExecution(dateVal, timeVal));
            }
        }
        // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/M_OSIsoft_AF_Asset_AFDataReference_GetValue_1.htm
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            // Important to note that the order of inputValues matches the order of inputAttributes.

            // Note that timeContext is an object.
            // We need to examine it further in order to resolve it to an AFTime.
            var time = ToAFTime(timeContext);

            AFValue measurement = null;
            AFValue low         = null;
            AFValue high        = null;
            AFValue lowlow      = null;
            AFValue highhigh    = null;

            // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/P_OSIsoft_AF_Asset_AFAttribute_Trait.htm
            // https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/T_OSIsoft_AF_Asset_AFAttributeTrait.htm
            for (var i = 0; i < inputAttributes.Count; i++)
            {
                if (i == 0)
                {
                    measurement = inputValues[i];
                }
                else if (inputAttributes[i].Trait == AFAttributeTrait.LimitLo)
                {
                    low = inputValues[i];
                }
                else if (inputAttributes[i].Trait == AFAttributeTrait.LimitHi)
                {
                    high = inputValues[i];
                }
                else if (inputAttributes[i].Trait == AFAttributeTrait.LimitLoLo)
                {
                    lowlow = inputValues[i];
                }
                else if (inputAttributes[i].Trait == AFAttributeTrait.LimitHiHi)
                {
                    highhigh = inputValues[i];
                }
            }
            // Remember any of the passed AFValues could be null if the limit trait is not defined.
            // This is a fact of life and reflects the many possibilities within a given process unit.
            return(Calculation(time, measurement
                               , low
                               , high
                               , lowlow
                               , highhigh));
        }
        static void Main(string[] args)
        {
            PISystems piSystems = new PISystems();
            foreach (PISystem piSystem in piSystems)
            {
                piSystem.Connect();
                Console.WriteLine("Nome do AF Server: {0}, TZ: {1}, Version: {2}", piSystem.Name, piSystem.ServerTimeZone, piSystem.ServerVersion);
            }
            PISystem defaultPISystem = piSystems.DefaultPISystem;
            Console.WriteLine("\nAF Databases\n");
            foreach (AFDatabase db in defaultPISystem.Databases)
            {
                Console.WriteLine("Nome do AFDatabase: {0}", db.Name);
            }
            AFDatabase afDb = defaultPISystem.Databases["Magical Power Company"];
            Console.WriteLine("\nRoot Elements\n");
            foreach (AFElement element in afDb.Elements)
            {
                Console.WriteLine("Nome dos elementos raízes: {0}", element.Name);
            }
            Console.WriteLine("\nBasic Meter Elements\n");
            foreach (AFElement element in afDb.Elements["Meters"].Elements.Where(m => m.Template.Name == "MeterBasic"))
            {
                Console.WriteLine("Nome dos elementos secundários: {0}, templates: {1}", element.Name, element.Template.Name);
            }

            Console.WriteLine("\nBasic Meter Attributes\n");
            foreach (AFAttribute attribute in afDb.Elements["Meters"].Elements[0].Attributes)
            {
                Console.WriteLine("Nome dos attributos: {0}, data reference: {1}, configString: {2}", attribute.Name, attribute.DataReferencePlugIn == null ? "No DR!" : attribute.DataReferencePlugIn.Name, attribute.ConfigString);
            }
            AFAttribute myAttribute = AFObject.FindObject(@"\\PISRV01\Magical Power Company\Meters\Meter001|Energy Usage") as AFAttribute;
            AFElementTemplate elementTemplate = myAttribute.Element.Template;
            AFAttributeTemplate attributeTemplate = myAttribute.Template;

            bool fullLoad = true;
            var elements = AFElement.FindElementsByTemplate(afDb, null, elementTemplate, false, AFSortField.ID, AFSortOrder.Ascending, 100);
            if (fullLoad)
                AFElement.LoadElements(elements);
            else
                AFElement.LoadAttributes(elements, new[] { attributeTemplate });

            List<AFAttribute> afAttributesList = elements.Select(m => m.Attributes[attributeTemplate.Name]).ToList();
            AFAttributeList attributeList = new AFAttributeList(afAttributesList);
            var results = attributeList.Data.EndOfStream();
        }
        private AFValue Calculate(AFTime time, AFAttributeList inputAttributes, AFValues inputValues)
        {
            if (time == null)
            {
                throw new ArgumentException("No timestamp");
            }

            if (inputValues.Count == 0)
            {
                throw new ArgumentException(Resources.ERR_NoInputValues);
            }

            int bit;

            if (!int.TryParse(fBit, out bit))
            {
                throw new ArgumentException(Resources.ERR_NoBitSpecified);
            }

            if (bit < 0 || bit > (int)BitEnum.bit31)
            {
                throw new ArgumentException(Resources.ERR_InvalidBit);
            }

            AFValue inVal  = inputValues[0];
            object  objVal = inVal.Value;

            if (inVal.IsGood && objVal != null)
            {
                if (BitmaskCore.IsIntVal(objVal))
                {
                    ulong curVal  = (ulong)BitmaskCore.ConvertToType(objVal, TypeCode.UInt64);
                    int   tempVal = BitmaskCore.GetBit(curVal, (byte)bit);
                    return(new AFValue(base.Attribute, tempVal, inVal.Timestamp, Attribute.DefaultUOM));
                }
                else
                {
                    throw new ArgumentException(Resources.ERR_SourceAttributeMustBeAnIntegerType);
                }
            }
            else
            {
                return(AFValue.CreateSystemStateValue(Attribute, AFSystemStateCode.BadInput, inVal.Timestamp));
            }
        }
Example #35
0
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            if (timeContext == null && inputAttributes == null)
            {
                throw new ArgumentNullException("Time context and/or input attributes cannot be null");
            }

            AFTimeRange timeRange;

            try
            {
                timeRange = (AFTimeRange)timeContext;
            }
            catch (InvalidCastException)
            {
                throw new InvalidCastException("Cannot cast timeContext to AFTimeRange");
            }

            IList <AFValues> vals = inputAttributes.Data.RecordedValues(
                timeRange: timeRange,
                boundaryType: AFBoundaryType.Inside,
                filterExpression: "",
                includeFilteredValues: false,
                pagingConfig: new PIPagingConfiguration(PIPageType.TagCount, 1000)).ToList();

            if (vals[0].Count != vals[1].Count)
            {
                throw new InvalidOperationException("Number of lat/long events do not match");
            }

            switch (SummaryType)
            {
            case "Distance":
                return(GetDistance(vals, timeRange));

            case "MaxSpeed":
                return(GetMaxSpeed(vals, timeRange));

            case "MinSpeed":
                return(GetMinSpeed(vals, timeRange));

            default:
                throw new InvalidOperationException("Invalid summary type");
            }
        }
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            if (!fChecked)
            {
                CheckConfig();
            }

            AFValue result;

            try {
                result = Calculate(inputValues);
            } catch {
                UnloadParameters();
                fChecked = false;
                throw;
            }
            return(result);
        }
        public void Run()
        {
            PISystems piSystems = new PISystems();
            PISystem  piSystem  = piSystems["<AFSERVER>"];

            AFDatabase afDatabase = piSystem.Databases["NuGreen"];

            AFCategory elementCategory   = afDatabase.ElementCategories["Equipment Assets"];
            AFCategory attributeCategory = afDatabase.AttributeCategories["Real-Time Data"];

            AFElementTemplate elementTemplate = afDatabase.ElementTemplates["Boiler"];

            const int pageSize   = 1000;
            int       startIndex = 0;
            int       totalCount;

            do
            {
                // Find all "Water Flow" attributes in the NuGreen database.
                AFAttributeList attrList = AFAttribute.FindElementAttributes(
                    database: afDatabase,
                    searchRoot: null,
                    nameFilter: "*",
                    elemCategory: elementCategory,
                    elemTemplate: elementTemplate,
                    elemType: AFElementType.Any,
                    attrNameFilter: "*",
                    attrCategory: attributeCategory,
                    attrType: TypeCode.Double,
                    searchFullHierarchy: true,
                    sortField: AFSortField.Name,
                    sortOrder: AFSortOrder.Ascending,
                    startIndex: startIndex,
                    maxCount: pageSize,
                    totalCount: out totalCount);

                foreach (AFAttribute attr in attrList)
                {
                    Console.WriteLine("Parent element name: {0}", attr.Element);
                }

                startIndex += pageSize;
            } while (startIndex < totalCount);
        }
        static void Main(string[] args)
        {
            NetworkCredential credential = new NetworkCredential(connectionInfo.user, connectionInfo.password);
            var piSystem = (new PISystems())[connectionInfo.AFServerName];

            Console.WriteLine($"connecting to : {connectionInfo.AFServerName} - {connectionInfo.AFDatabaseName}");
            piSystem.Connect(credential);
            var afdb = piSystem.Databases[connectionInfo.AFDatabaseName];

            Console.WriteLine("connected");

            //element search
            var query  = "Template:'Antimatter Relay'";
            var search = new AFElementSearch(afdb, "Relay Search", query);

            var results  = search.FindElements(0, true, 1000);
            var attrList = new AFAttributeList();

            foreach (var element in results)
            {
                Console.WriteLine($"{element.Name}");
                foreach (var attribute in element.Attributes)
                {
                    //not optimized
                    //var snapShot = attribute.GetValue();
                    //Console.WriteLine($"{attribute.Name}: {snapShot.Value.ToString()} {snapShot.UOM}");

                    //optimized
                    attrList.Add(attribute);
                }
            }

            //one call to get values
            var snapShots = attrList.GetValue();

            foreach (var snapShot in snapShots)
            {
                Console.WriteLine($"Element: {snapShot.Attribute.Element.Name} - {snapShot.Attribute.Name}: {snapShot.Value.ToString()} {snapShot.UOM}");
            }

            Console.WriteLine("completed execution");
            //Console.ReadKey();
        }
        public static async Task<IList<IDictionary<AFSummaryTypes, AFValue>>> GetSummariesAsyncThrottled(AFAttributeList attributeList, int numConcurrent)
        {
            // Use "asynchronous semaphore" pattern (e.g. SemaphoreSlim.WaitAsync()) to throttle the calls

            Console.WriteLine("Calling GetSummariesAsyncThrottled");

            // Example: Limit to numConcurrent concurrent async I/O operations.
            SemaphoreSlim throttler = new SemaphoreSlim(initialCount: numConcurrent);

            Task<IDictionary<AFSummaryTypes, AFValue>>[] tasks = attributeList
                // Do not make the call if async is not supported
                .Where(attr => (attr.SupportedDataMethods & AFDataMethods.Asynchronous) == AFDataMethods.Asynchronous)
                .Select(async attr =>
                {
                    // asychronously try to acquire the semaphore
                    await throttler.WaitAsync();

                    try
                    {
                        AFSummaryTypes mySummaries = AFSummaryTypes.Minimum | AFSummaryTypes.Maximum | AFSummaryTypes.Average | AFSummaryTypes.Total;
                        AFTimeRange timeRange = new AFTimeRange(new AFTime("*-1d"), new AFTime("*"));

                        return await attr.Data.SummaryAsync(
                            timeRange: timeRange,
                            summaryType: mySummaries,
                            calculationBasis: AFCalculationBasis.TimeWeighted,
                            timeType: AFTimestampCalculation.Auto);
                    }
                    catch (AggregateException ae)
                    {
                        Console.WriteLine("{0}: {1}", attr.Name, ae.Flatten().InnerException.Message);
                        return null;
                    }
                    finally
                    {
                        // release the resource
                        throttler.Release();
                    }
                })
                .ToArray();

            return await Task.WhenAll(tasks);
        }
        public void Run()
        {
            string processFeedRate = @"\\<AFSERVER>\NuGreen\NuGreen\Houston\Cracking Process\Equipment\B-210|Process Feedrate";
            string waterFlow = @"\\<AFSERVER>\NuGreen\NuGreen\Houston\Cracking Process\Equipment\B-210|Water Flow";

            // Directly locate the AFAttribute of interest by passing in the AF path.
            // A similar method FindElementsByPath can be used to directly locate elements.
            AFKeyedResults<string,AFAttribute> results = AFAttribute.FindAttributesByPath(new[] { processFeedRate, waterFlow }, null);

            AFAttribute processFeedRateAttribute = results[processFeedRate];
            AFAttribute waterFlowAttribute = results[waterFlow];

            AFAttributeList attrList = new AFAttributeList(new[] { processFeedRateAttribute, waterFlowAttribute });
            // Make a bulk call to get values.
            AFValues values = attrList.GetValue();

            foreach (AFValue val in values)
            {
                Console.WriteLine("Attribute: {0}", val.Attribute);
                Console.WriteLine("Timestamp: {0}, Value: {1}", val.Timestamp, val.Value.ToString());
                Console.WriteLine();
            }
        }
Example #41
0
        // Return latest value if timeContext is null, otherwise return latest value before a specific time
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            AFValue currentVal = new AFValue();
            DateTime time;
            if (timeContext != null)
            {
                time = ((AFTime)timeContext).LocalTime;
            }
            else
            {
                time = DateTime.Now;
            }
            using (SqlDataReader reader = SQLHelper.GetSQLData(SQLName, DBName, TableName, DateTime.MinValue, time))
            {
                if (reader.Read())
                {
                    currentVal.Timestamp = AFTime.Parse(reader["pi_time"].ToString());
                    currentVal.Value = reader["pi_value"];
                }
            }

            return currentVal;
        }
        public static async Task<IList<IDictionary<AFSummaryTypes, AFValue>>> GetSummariesAsyncWithTimeout(AFAttributeList attributeList, int timeoutInMilliseconds)
        {
            // Use a "competing tasks" pattern to place timeout on multiple async requests

            Console.WriteLine("Calling GetSummariesAsyncWithTimeout");

            CancellationTokenSource cts = new CancellationTokenSource();
            CancellationToken token = cts.Token;
            CancellationTokenSource ctsForTimer = new CancellationTokenSource();
            CancellationToken tokenForTimer = ctsForTimer.Token;

            Task<IDictionary<AFSummaryTypes, AFValue>>[] tasks = attributeList
                // Do not make the call if async is not supported
                .Where(attr => (attr.SupportedDataMethods & AFDataMethods.Asynchronous) == AFDataMethods.Asynchronous)
                .Select(async attr =>
                {
                    try
                    {
                        AFSummaryTypes mySummaries = AFSummaryTypes.Minimum | AFSummaryTypes.Maximum | AFSummaryTypes.Average | AFSummaryTypes.Total;
                        AFTimeRange timeRange = new AFTimeRange(new AFTime("*-1d"), new AFTime("*"));

                        return await attr.Data.SummaryAsync(
                            timeRange: timeRange,
                            summaryType: mySummaries,
                            calculationBasis: AFCalculationBasis.TimeWeighted,
                            timeType: AFTimestampCalculation.Auto,
                            cancellationToken: token);
                    }
                    catch (AggregateException ae)
                    {
                        Console.WriteLine("{0}: {1}", attr.Element.Name, ae.Flatten().InnerException.Message);
                        return null;
                    }
                    catch (OperationCanceledException oe)
                    {
                        Console.WriteLine("{0}: {1}", attr.Element.Name, oe.Message);
                        return null;
                    }
                })
                .ToArray();

            // Define a task that completes when all subtasks are complete
            Task<IDictionary<AFSummaryTypes, AFValue>[]> task = Task.WhenAll(tasks);

            // Asychronously wait for either the summaries or timer task to complete
            if (await Task.WhenAny(task, Task.Delay(timeoutInMilliseconds, tokenForTimer)) == task)
            {
                // Cancel the timer task
                ctsForTimer.Cancel();
                // Return summaries result
                return task.Result;
            }
            else
            {
                // Cancel the summaries task if timeout
                cts.Cancel();
                throw new TimeoutException("The operation has timed out.");
            }
        }
        /// <summary>
        /// This method gets a collection of AFValue objects for an attribute based upon the data reference configuration within the specified AFTimeRange context.
        /// <see cref="https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/M_OSIsoft_AF_Asset_AFDataReference_GetValues.htm"/>
        /// </summary>
        public override AFValues GetValues(object context, AFTimeRange timeRange, int numberOfValues, AFAttributeList inputAttributes,
            AFValues[] inputValues)
        {
            var afvalues = new AFValues();

            //insert logic to generate af values here
            afvalues.Add(new AFValue()
            {
                Value = 0,
                Timestamp = new AFTime(timeRange.StartTime)
            });

            afvalues.Add(new AFValue()
            {
                Value = 1,
                Timestamp = new AFTime(timeRange.EndTime)
            });

            return afvalues;
        }
 /// <summary>
 /// This method gets the value for multiple attributes based upon the data reference configuration within the specified context.
 /// </summary>
 /// <param name="attributes">The list of attributes to obtain the value of. The returned collection of AFValues will be specified in the same order as the list of attributes provided.</param>
 /// <param name="context">The AF SDK context to be used when getting the attributes' value. If the context is not null, then the value will be returned relative to the specified AF SDK object. The following AF SDK objects may be used as a context: AFCase, AFAnalysis, and AFModel. It is up to the data reference to determine how the context should be used when retrieving the attribute's value.</param>
 /// <param name="timeContext">The time context. If the context is null, then the most recent value is returned. If the context is an AFTime object, then the value at the specified time is returned. If the context is an AFTimeRange object, then the value for the specified time range is returned. For convenience, AF SDK will convert a time context of AFCase into a time range, time at case's end time, or null as appropriate.</param>
 /// <remarks>This method provides a mechanism to read multiple attribute values in one call, giving the data reference an opportunity to provide for faster performance than if retrieved by individual calls. Because this method is static, it must be overridden using the 'new' keyword in C#, or 'Shadows' in VB.NET. If this method is not provided in the Data Reference implementation, then the SDK will invoke the GetValue call for each attribute.</remarks>
 /// <see cref="https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/M_OSIsoft_AF_Asset_AFDataReference_GetValue.htm"/>
 /// <returns></returns>
 public static new AFValue GetValue(AFAttributeList attributes, Object context, Object timeContext)
 {
     return null;
 }
 /// <summary>
 /// This method gets the value based upon the data reference configuration within the specified context.
 /// <see cref="https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/M_OSIsoft_AF_Asset_AFDataReference_GetValue_1.htm"/>
 /// </summary>
 public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
 {
     return new AFValue()
     {
         Timestamp = DateTime.Now,
         Value = 0
     };
 }
Example #46
0
        public override AFAttributeList GetInputs(object context)
        {
            AFAttributeList attList = new AFAttributeList();

            attList.Add(this.Attribute.Element.Attributes["Latitude"]);
            attList.Add(this.Attribute.Element.Attributes["Longitude"]);

            _uomMeter = Attribute.PISystem.UOMDatabase.UOMs["meter"];
            _uomMPH = Attribute.PISystem.UOMDatabase.UOMs["mile per hour"];

            return attList;
        }
Example #47
0
        public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
        {
            if (timeContext == null && inputAttributes == null) throw new ArgumentNullException("Time context and/or input attributes cannot be null");

            AFTimeRange timeRange;
            try
            {
                timeRange = (AFTimeRange) timeContext;
            }
            catch (InvalidCastException)
            {
                throw new InvalidCastException("Cannot cast timeContext to AFTimeRange");
            }

            IList<AFValues> vals = inputAttributes.Data.RecordedValues(
                timeRange: timeRange,
                boundaryType: AFBoundaryType.Inside,
                filterExpression: "",
                includeFilteredValues: false,
                pagingConfig: new PIPagingConfiguration(PIPageType.TagCount, 1000)).ToList();

            if (vals[0].Count != vals[1].Count) throw new InvalidOperationException("Number of lat/long events do not match");

            switch (SummaryType)
            {
                case "Distance":
                    return GetDistance(vals, timeRange);
                case "MaxSpeed":
                    return GetMaxSpeed(vals, timeRange);
                case "MinSpeed":
                    return GetMinSpeed(vals, timeRange);
                default:
                    throw new InvalidOperationException("Invalid summary type");
            }
        }
Example #48
0
 // Return all values (converted to AFValues) over a specific time interval
 public override AFValues GetValues(object context, AFTimeRange timeRange, int numberOfValues, AFAttributeList inputAttributes, AFValues[] inputValues)
 {
     AFValues values = new AFValues();
     DateTime startTime = timeRange.StartTime.LocalTime;
     DateTime endTime = timeRange.EndTime.LocalTime;
     using (SqlDataReader reader = SQLHelper.GetSQLData(SQLName, DBName, TableName, startTime, endTime))
     {
         while (reader.Read())
         {
             AFValue newVal = new AFValue();
             newVal.Timestamp = AFTime.Parse(reader["pi_time"].ToString());
             newVal.Value = reader["pi_value"];
             values.Add(newVal);
         }
     }
     return values;
 }
        public override void Run()
        {
            try
            {

                var connection = new AfConnectionMgr(Server, Database);
                connection.Connect();

                AFDatabase database = connection.GetDatabase();

                var afObject = AFObject.FindObject(AttributePath, database);

                var separator = CultureInfo.CurrentCulture.TextInfo.ListSeparator;

                if (afObject is AFAttribute)
                {
                    var attribute = (AFAttribute)afObject;
                    AFValue value = attribute.GetValue();
                    Console.WriteLine("{0}{1}{2}{3}{4}", GetStringValue(value), separator, value.Timestamp,separator, attribute.Name);
                }

                if (afObject is AFElement)
                {

                    var element = (AFElement)afObject;

                    // the attibute list object allows a single GetValue() call for all attributes at same time.
                    // We call this a "Bulk Call"
                    var attributes = new AFAttributeList(element.Attributes);
                    var values=attributes.GetValue();

                    // prints the results
                    values.ForEach((afvalue)=> Console.WriteLine("{0}{1}{2}{3}{4}", GetStringValue(afvalue),separator, afvalue.Timestamp,separator,afvalue.Attribute.Name));
                }

            }

            catch (Exception ex)
            {
                this.Logger.Error(ex);
            }
        }
        /// <summary>
        /// Set AF Attribute's ConfigString based on existing PI points
        /// </summary>
        /// <param name="attributes"></param>
        private static void SetConfigStrings(IList<AFAttribute> attributes)
        {
            AFAttributeList attrList = new AFAttributeList(attributes);
            var points = attrList.GetPIPoint();

            IList<string> configStrings = new List<string>(attrList.Count);

            foreach (var attrPoint in points.Results)
            {
                AFAttribute attribute = attrPoint.Key;
                string configString = attrPoint.Value.GetPath(AFEncodeType.NameThenID).Replace(";{", "?").Replace("}", "").Replace(";?", "?");
                configStrings.Add(configString);
            }

            AFAttribute.SetConfigStrings(attrList, configStrings);
        }
        static void PrintEnergyUsageAtTime(AFDatabase database, string timeStamp)
        {
            Console.WriteLine("Print Energy Usage at Time: {0}", timeStamp);
            AFAttributeList attrList = new AFAttributeList();

            // Use this method if you get stuck trying to find attributes
            // attrList = GetAttribute();

            // Your code here
        }
        static void PrintDailyAverageEnergyUsage(AFDatabase database, string startTime, string endTime)
        {
            Console.WriteLine(string.Format("Print Daily Energy Usage - Start: {0}, End: {1}", startTime, endTime));
            AFAttributeList attrList = new AFAttributeList();

            // Use this method if you get stuck trying to find attributes
            // attrList = GetAttribute();
        }