6 Replies Latest reply on May 12, 2015 6:31 PM by jstuder07

    What function does Sharepoint/ProcessBook use to retrieve AF values?

    jstuder07

      I have created a custom AF Plugin that seems to work on many
      client types (System Explorer, Notifications, Coresight2014),  but not Sharepoint 2010 & ProcessBook. The
      plugin inherits the Formula DLL, but overrides the GetValue() function to
      either return a value of “N/A” if certain conditions are met, or perform the
      normal base.GetValue() function for the formula data reference. I am finding
      that the attributes are correctly displaying “N/A” for System Explorer,
      Notifications, and Coresight 2014. However, it looks like Sharepoint is
      ignoring the custom logic and returning what would be evaluated by the normal
      formula functionality. The Sharepoint Webpart displays are SVG files created
      via ProcessBook. Is Sharepoint using a different function call than GetValue()
      that I need to override?

       

      Thanks in advance.

        • Re: What function does Sharepoint/ProcessBook use to retrieve AF values?
          bshang

          Hi Justin,

           

          Could you post the source code of the custom DR? If the entire code cannot be shared, then it would helpful to have the GetValue() portion. Can you let us know how the custom DR was registered? Was it built to target the .NET 3.5 or .NET 4.0 Frameoworks? Technically only .NET 3.5 is supported, so I would try to verify that first.

           

          Also, you mentioned the incorrect behavior in Sharepoint. Does the custom DR show the correct value in Processbook itself? If so, then it may be a caching issue on Sharepoint, but let's try to verify the behavior on Processbook itself first.

           

          Note that Processbook calls AFDataReference.PlotValues() to plot the value on a trend. Does the PDI use Trend or Value symbols?

            • Re: What function does Sharepoint/ProcessBook use to retrieve AF values?
              jstuder07

              Hi  Baryy,

               

              I built the plugin using .Net 4.0. If I try building against 3.5, I get compile errors for the version of the AF-SDK that I am using.

               

              I verified that the incorrect behavior is also shown in ProcessBook, so it makes sense to take a step back and turn our focus there. I am using a Value symbol, not a trend. Below is the entire code:

               

              using System;
              using System.ComponentModel;
              using System.Globalization;
              using System.Runtime.InteropServices;
              using System.Text;
              using OSIsoft.AF.Asset;
              using OSIsoft.AF.EventFrame;
              using OSIsoft.AF.UnitsOfMeasure;
              using OSIsoft.AF.Time;

              namespace FormulaNA
              {
                  // Implementation of the data reference
                  [Serializable]
                  [Guid("9B87986D-4F48-4678-9FC9-9D089319656D")]
                  [Description("FormulaNA;Inherits Formula Plugin, but displays 'NA' if an input references a placeholder PI tag.")]
                  public class FormulaNA : OSIsoft.AF.Asset.DataReference.FormulaDR
                  {
                      public FormulaNA()
                          : base()
                      {
                      }

                      #region Implementation of AFDataReference

                      public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
                      {
                          AFTime timestamp = AFTime.MinValue;
                          bool tempAttributeHasPlaceholderInputs = false;

                          try
                          {
                              if (inputAttributes != null)
                              {
                                  //Get Timestamp
                                  foreach (AFValue inVal in inputValues)
                                  {
                                      if (inVal.Timestamp > timestamp)
                                          timestamp = inVal.Timestamp;
                                  }

                                  //Determine whether to output N/A (if placeholder tag exists as an input) or to use the normal formula plugin logic
                                  foreach (AFAttribute inputAttribute in inputAttributes)
                                  {
                                      if (tempAttributeHasPlaceholderInputs == false)
                                      {
                                          tempAttributeHasPlaceholderInputs = AttributeHasPlaceholderInputs(inputAttribute);
                                      }
                                  }
                              }
                              else
                              {
                                  tempAttributeHasPlaceholderInputs = false;
                              }

                              //Return Value
                              if (tempAttributeHasPlaceholderInputs == false)
                              {
                                  return base.GetValue(context, timeContext, inputAttributes, inputValues);
                              }
                              else
                              {
                                  AFAttribute myAFAtribute = base.GetAttribute(".");

                                  if (myAFAtribute.Type.ToString().IndexOf("AFEnumeration") == -1)
                                  {
                                      return new AFValue("N/A", timestamp, null, AFValueStatus.Bad);
                                  }
                                  else
                                  {
                                      //If the enumeration set contains an "N/A" state, then use that state value instead by using a "Good" status to allow the conversion.
                                      //Note: It is assumed that any enumeration attribute that uses this data reference will have an "N/A" state configured.
                                      //      Otherwise, an error stating "Cannot convert value" will be thrown.
                                      return new AFValue("N/A", timestamp, null, AFValueStatus.Good);
                                  }
                              }
                          }
                          catch
                          {
                              throw;
                          }
                      }

                      public bool AttributeHasPlaceholderInputs(AFAttribute myAttribute)
                      {
                          bool tempAttributeHasPlaceholderInputs = false;

                          if (myAttribute.DataReference != null)
                          {
                              if (myAttribute.DataReference.Name == "PI Point")
                              {
                                  if (myAttribute.RawPIPointPath(OSIsoft.AF.AFEncodeType.Name).ToUpper().IndexOf("EA_PLACEHOLDERTAG_N/A") != -1)
                                  {
                                      tempAttributeHasPlaceholderInputs = true;
                                  }
                              }
                              else if (myAttribute.DataReference.Name == "FormulaNA")
                              {
                                  //Assumed that the FormulaNA attribute value will be "N/A" if placeholder tags are used as inputs.
                                  if ((myAttribute.GetValue(AFTime.Now).ToString() == "N/A"))
                                  {
                                      tempAttributeHasPlaceholderInputs = true;
                                  }
                              }
                              else if ((myAttribute.DataReference.Name == "Formula") || (myAttribute.DataReference.Name == "Table Lookup"))
                              {
                                  AFAttributeList InputAttributeList;

                                  InputAttributeList = myAttribute.DataReference.GetInputs(OSIsoft.AF.Asset.AFDataReferenceContext.Model);

                                  foreach (AFAttribute inputAttribute in InputAttributeList)
                                  {
                                      if (tempAttributeHasPlaceholderInputs == false)
                                      {
                                          tempAttributeHasPlaceholderInputs = AttributeHasPlaceholderInputs(inputAttribute);
                                      }
                                  }
                              }
                          }

                          return tempAttributeHasPlaceholderInputs;
                      }

                      #endregion
                  }


              }

                • Re: What function does Sharepoint/ProcessBook use to retrieve AF values?
                  bshang

                  Thanks for the code. Can we try to rebuild the custom DR targeting .NET 3.5? The AF SDK reference will need to be changed to the 2.0.0.0 assembly version (which is built under 3.5 Framework version).

                   

                  via Add Reference>Assembllies>Extensions>.

                   

                  afassembly.PNG

                   

                   

                  Then, unregister the 4.0 plugin and register the 3.5 plugin using regplugin.

                   

                  The reason I'd like to try this is because the AF2 add-in for Processbook is built with .NET 3.5 Framework (2.0 runtime), and sometimes, there will be issues when a custom DR targeting .NET 4.0 is loaded.

                   

                  Does the custom DR show a numeric value for the Value symbol or is there an error string instead?

                  1 of 1 people found this helpful
                    • Re: What function does Sharepoint/ProcessBook use to retrieve AF values?
                      bshang

                      Hi Justin,

                       

                      I was able to reproduce the issue using FormulaNA compiled against .NET Framework 4.5 and referencing AF SDK 4.0.0.0 assembly version.

                       

                      However, compiling FormulaNA to target .NET Framework 3.5 and referencing AF SDK 2.0.0.0 assembly version (which also targets .NET 3.5) worked. Processbook then gave the expected "N/A". Interestingly, having FormulaNA target 4.5 and referencing AF SDK 2.0.0.0 also worked. My guess for these behaviors is due to the fact that OSIsoft.AF.Asset.DataReference.Formula is running under the v2.0.50727 runtime (targets 3.5), and using AF SDK 4.0.0.0 assembly version causes some issues with object references between assemblies. It'll probably be a nice debugging exercise to find out exactly why. Please let us know though if you find the same behavior using the above settings.

                      1 of 1 people found this helpful
                        • Re: What function does Sharepoint/ProcessBook use to retrieve AF values?
                          dng

                          Interesting findings, Barry.

                           

                          Justin, one other troubleshooting tool you can use would be to use process explorer to see if the FormulaNA assembly is loaded by ProcessBook (or any other problematic client applications).

                           

                          If you ultimately found out that the target .NET Framework is indeed the issue, keep in mind you can have both .NET 3.5 and .NET 4.0 versions of the plug-in registered. AF supports side-by-side registration of plugins for different .NET CLR versions (2.0 and 4.0). Make sure the GUID and Assembly ID are identical. Applications (e.g. AF2 add-in in ProcessBook) that requires .NET 3.5 will load the .NET 3.5 version, while other applications can use the .NET 4.0 version if available.

                           

                          I'm surprised to see that the .NET 4 custom data reference works in PI Notifications though because the service is a .NET 3.5 process and should not be able to load plugins (e.g. data references or delivery channels) that are built against the .NET 4 runtime.

                          1 of 1 people found this helpful
                          • Re: What function does Sharepoint/ProcessBook use to retrieve AF values?
                            jstuder07

                            Thanks Barry & Daphne.

                             

                            That solved my issue. I had to fight with Sharepoint because it wasn't picking up on the DLL change. However, after deleting the DLL on the Sharepoint server and perform an IISReset, the .NET 3.5 DLL got copied over and all was right in the world.

                             

                            Thanks again for the quick responses.