private void queueBackfill(AFAnalysisService service, AFTimeRange timeRange)
        {
            string outNotQueueReason;
            bool   canQueue = service.CanQueueCalculation(out outNotQueueReason);

            if (canQueue)
            {
                var queueResponse = service
                                    .QueueCalculation(selectedAnalyses, timeRange, backfillCalcMode);
                string message;
                message = String.Format("{0} - {1} {2} {3}"
                                        , DateTime.Now.ToString()
                                        , selectedAnalyses.Count.ToString()
                                        , "Analyses Backfill queued successfully. Request ID:"
                                        , queueResponse.ToString());
                lbLog.Items.Add(message);
            }
            else
            {
                string message;
                message = String.Format("{0} - {1}"
                                        , DateTime.Now.ToString()
                                        , "AF Analysis Service is not available for queuing...");
                lbLog.Items.Add(message);
                message = String.Format("{0} - Reason: {1}"
                                        , DateTime.Now.ToString()
                                        , outNotQueueReason);
                lbLog.Items.Add(message);
            }
        }
Ejemplo n.º 2
0
        static void Main(string[] args)
        {
            //define variables
            string user_path           = null;
            string user_serv           = null;
            string user_db             = null;
            string user_analysisfilter = null;
            string user_mode           = null;

            PIServer                 aPIServer        = null;
            PISystems                aSystems         = new PISystems();
            PISystem                 aSystem          = null;
            AFAnalysisService        aAnalysisService = null;
            AFDatabase               aDatabase        = null;
            List <AFElement>         foundElements    = new List <AFElement>();
            List <AFAnalysis>        foundAnalyses    = new List <AFAnalysis>();
            IEnumerable <AFAnalysis> elemAnalyses     = null;

            AFTimeRange backfillPeriod = new AFTimeRange();

            AFAnalysisService.CalculationMode mode = AFAnalysisService.CalculationMode.FillDataGaps;
            String reason   = null;
            Object response = null;

            String help_message = "This utility backfills/recalculates analyses.  Generic syntax: "
                                  + "\n\tAnalysisBackfill.exe \\\\AFServer\\AFDatabase\\pathToElement\\AFElement AnalysisNameFilter StartTime EndTime Mode"
                                  + "\n This utility supports two modes: backfill and recalc.  Backfill will fill in data gaps only.  Recalc will replace all values.  Examples:"
                                  + "\n\tAnalysisBackfill.exe \\\\AF1\\TestDB\\Plant1\\Pump1 FlowRate_*Avg '*-10d' '*' recalc"
                                  + "\n\tAnalysisBackfill.exe \\\\AF1\\TestDB\\Plant1\\Pump1 *Rollup '*-10d' '*' backfill";

            //bad input handling & help
            if (args.Length < 5 || args.Contains("?"))
            {
                Console.WriteLine(help_message);
                Environment.Exit(0);
            }

            try
            {
                //parse inputs and connect
                user_path = args[0];
                var inputs = user_path.Split('\\');
                user_serv = inputs[2];
                user_db   = inputs[3];

                //connect
                AFSystemHelper.Connect(user_serv, user_db);
                aSystem          = aSystems[user_serv];
                aDatabase        = aSystem.Databases[user_db];
                aAnalysisService = aSystem.AnalysisService;

                /* check versions.  need to write this.
                 * aSystem.ServerVersion
                 * aSystems.Version
                 * aPIServer.ServerVersion
                 */

                //find AFElements
                //will eventually include element search filter as well
                if (inputs.Length == 4)
                { //all elements in database
                    foundElements = AFElement.FindElements(aDatabase, null, null, AFSearchField.Name, true, AFSortField.Name, AFSortOrder.Ascending, 1000).ToList();
                }
                else
                { //single element
                    var prelength = user_serv.Length + user_db.Length;
                    var path1     = user_path.Substring(prelength + 4, user_path.Length - prelength - 4);
                    foundElements.Add((AFElement)AFObject.FindObject(path1, aDatabase));
                }

                //other inputs
                user_analysisfilter = args[1];
                AFTime backfillStartTime = new AFTime(args[2].Trim('\''));
                AFTime backfillEndTime   = new AFTime(args[3].Trim('\''));
                backfillPeriod = new AFTimeRange(backfillStartTime, backfillEndTime);

                //user_mode
                user_mode = args[4];
                switch (user_mode.ToLower())
                {
                case "recalc":
                    mode = AFAnalysisService.CalculationMode.DeleteExistingData;
                    break;

                case "backfill":
                    mode = AFAnalysisService.CalculationMode.FillDataGaps;
                    break;

                default:
                    Console.WriteLine("Invalid mode specified.  Supported modes: backfill, recalc");
                    Environment.Exit(0);
                    break;
                }

                Console.WriteLine("Requested backfills/recalculations:");

                foreach (AFElement elem_n in foundElements)
                {
                    //find analyses
                    String           analysisfilter = "Target:=\"" + elem_n.GetPath(aDatabase) + "\" Name:=\"" + user_analysisfilter + "\"";
                    AFAnalysisSearch analysisSearch = new AFAnalysisSearch(aDatabase, "analysisSearch", AFAnalysisSearch.ParseQuery(analysisfilter));
                    elemAnalyses = analysisSearch.FindAnalyses(0, true).ToList();

                    //print details to user
                    Console.WriteLine("\tElement: " + elem_n.GetPath().ToString()
                                      + "\n\tAnalyses (" + elemAnalyses.Count() + "):");

                    if (elemAnalyses.Count() == 0)
                    {
                        Console.WriteLine("\t\tNo analyses on this AF Element match the analysis filter.");
                    }
                    else
                    {
                        foundAnalyses.AddRange(elemAnalyses);
                        foreach (var analysis_n in elemAnalyses)
                        {
                            Console.WriteLine("\t\t{0}, {1}, Outputs:{2}", analysis_n.Name, analysis_n.AnalysisRule.Name, analysis_n.AnalysisRule.GetOutputs().Count);
                        }
                    }

                    /* to check for dependent analyses
                     * foreach (var analysis_n in foundAnalyses)
                     * {
                     *
                     * }
                     */
                }
                Console.WriteLine("\nTime range: " + backfillPeriod.ToString() + ", " + "{0}d {1}h {2}m {3}s."
                                  , backfillPeriod.Span.Days, backfillPeriod.Span.Hours, backfillPeriod.Span.Minutes, backfillPeriod.Span.Seconds);
                Console.WriteLine("Mode: " + user_mode + "=" + mode.ToString());
                //implement wait time
                Console.WriteLine("\nA total of {0} analyses will be queued for processing in 10 seconds.  Press Ctrl+C to cancel.", foundAnalyses.Count);
                DateTime beginWait = DateTime.Now;
                while (!Console.KeyAvailable && DateTime.Now.Subtract(beginWait).TotalSeconds < 10)
                {
                    Console.Write(".");
                    Thread.Sleep(250);
                }
                //no status check
                Console.WriteLine("\n\nAll analyses have been queued.\nThere is no status check after the backfill/recalculate is queued (until AF 2.9.0). Please verify by using other means.", foundAnalyses.Count);

                //queue analyses for backfill/recalc
                foreach (var analysis_n in foundAnalyses)
                {
                    response = aAnalysisService.QueueCalculation(new List <AFAnalysis> {
                        analysis_n
                    }, backfillPeriod, mode);

                    /* no status check info
                     * in AF 2.9, QueueCalculation will allow for true status checking. In AF 2.8.5, it is not possible to check.
                     * Documentation (https://techsupport.osisoft.com/Documentation/PI-AF-SDK/html/M_OSIsoft_AF_Analysis_AFAnalysisService_ToString.htm) states:
                     * This method queues the list of analyses on the analysis service to be calculated.
                     * The operation is asynchronous and returning of the method does not indicate that queued analyses were calculated.
                     * The status can be queried in the upcoming releases using the returned handle.
                     */

                    //Might be able to add a few check mechanisms using AFAnalysis.GetResolvedOutputs and the number of values in AFTimeRange
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error returned: " + ex.Message);
                Environment.Exit(0);
            }
        }