12 Replies Latest reply on Feb 25, 2015 9:42 AM by vincent.spaa

    How can I handle 1-1-1970 being passed to my GetValue method?

    vincent.spaa

      I have a custom data reference which has the following implementation of GetValue and GetValues:

       

      public override AFValues GetValues(object context, AFTimeRange timeRange, int numberOfValues,
          AFAttributeList inputAttributes, AFValues[] inputValues)
      {
          AFValues valuesCollection = new AFValues();
          DateTime start = timeRange.StartTime.LocalTime;
          start = new DateTime(start.Year, start.Month, start.Day, start.Hour, 0, 0, DateTimeKind.Local);
          DateTime end = timeRange.EndTime.LocalTime;
          end = new DateTime(end.Year, end.Month, end.Day, end.Hour, 0, 0, DateTimeKind.Local);
      
          while (start <= end)
          {
              valuesCollection.Add(Calculate(start));
              start = start.AddHours(1);
          }
      
          return valuesCollection;
      }
      
      public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
      {
          CheckConfig();
      
          AFTime time = timeContext == null
              ? DateTime.Now
              : ((AFTime)timeContext).LocalTime;
      
          return Calculate((time).LocalTime);
      }
      
      And the following relevant properties:
      
      public override AFDataReferenceMethod SupportedMethods
      {
          get
          {
              return AFDataReferenceMethod.GetValue | AFDataReferenceMethod.GetValues;
          }
      }
      
      public override OSIsoft.AF.Data.AFDataMethods SupportedDataMethods
      {
          get { return DefaultSupportedDataMethods; }
      }
      

      When using the new AF SDK (2.6), AF Client (2014) and DataLink (2014) everything works fine. The timestamp passed to GetValue and GetValues is exactly as I'd expect.

      When I switch to AF SDK 2.5.2 and DataLink 2013 I get some strange behavior. Trending the values in Processbook still works fine but running PISampData from DataLink results in 1-1-1970 being passed to the timeContext parameter of my GetValue method.

      Needless to say, this causes the Data Reference to produce the wrong values.

       

      As mentioned in this discussion: How can I handle a call to GetValues in a custom DR? (which is about the same data reference), the inputAttributes and inputValues are empty since the data reference does not use data from anything other than 2 AF Tables.

       

      Is there something I need to add to be backwards compatible with the older AF SDK?

        • Re: How can I handle 1-1-1970 being passed to my GetValue method?
          dng

          Hi Vincent,

           

          What .NET version is the custom data reference targeting? What version of the AF SDK is your development machine using? Since the last discussion, did you implement any RDA methods?


          It looks like we have changed the implementation of interpolation in AF SDK 2.6 to fix an issue where it is always calling into GetValues with timestamp of AFAttribute.DefaultTimeStamp. Let me look at it more closely to see if this is in fact the issue you are experiencing, and propose some workaround. Meanwhile, you can find some additional information at this previous thread: https://pisquare.osisoft.com/thread/5659.

          1 of 1 people found this helpful
            • Re: How can I handle 1-1-1970 being passed to my GetValue method?
              vincent.spaa

              Hello Daphne,

               

              No, I haven't implemented any additional RDA methods since the last discussion.

              After reading the topic you linked to I created two projects with one building against the (.net) 4.0 AFSDK and the other building against the old 2.0 SDK.

              Registering the 4.0 assembly makes DataLink work but I suspect (can't test right now) it will break Processbook support.

               

              So the question is now, how can I register both assemblies without having regplugin64 complain?

              The people from the other discussion you linked to didn't explain that part in detail (or I missed it while reading ..), just that it fixed their issue.

              And I found this discussion Using Regplugin to register datareference and support assembly but when I run regplugin on the .net 4.0 file in the 4.0 folder, it tells me there's another file already registered by that name.

               

              Thanks again for your swift response btw.

                • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                  dng

                  Hi Vincent,

                   

                  When using PISampData, PI DataLink first checks to see if InterpolatedValues is supported by the data reference. If so, it uses the RDA call AFAttribute.Data.InterpolatedValues to get the data; if not, it returns a message saying that the method is not supported.


                  In your custom data reference, you are specifying the supported data methods for your CDR as "DefaultSupportedDataMethods". This means you are explicitly opting-in for RDA methods such as InterpolatedValues, RecordedValues, PlotValues, Summaries, etc. If you did not override these RDA methods in your data reference, you are using the base class implementation for them. Since your data reference does not return any attribute in GetInputs, you need to implement your RDA methods to provide proper support for application that uses RDA methods to get the data.


                  Now, due to the bug in AF SDK 2.5 (WI 96443), and since you are using the base implementation for InterpolatedValues with no inputs, you are getting the AFAttribute.DefaultTimeStamp passed to GetValues instead of the proper interpolated values. If your data reference needs to work with PI DataLink 2013, one workaround would be to override the base implementation for InterpolatedValues. The other option is the upgrade AF SDK to 2.6 on the PI DataLink 2013 machine.


                  Regarding your latest question on registering both assemblies with RegPlugIn, you can use the /force parameter to register your 2.0 assembly after the 4.0 assembly is registered. Make sure you have the same GUID for the plugins. Based on the .NET runtime version of the client application, the appropriate plug-in version will be loaded. In fact, if you look closely at the PIPoint Data Reference (e.g. by running RegPlugIn /list), you can see that two versions of the plug-in.

                  1 of 1 people found this helpful
                    • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                      vincent.spaa

                      Your answer cleared up a few things for me, thank you.

                      I finally managed to get both version registered at the same time by calling regplugin with "/unregister" beforehand.

                      So with the workaround it seems to work just fine now. Upgrading to 2.6 is not an option for the customer at this time, so I guess they'll have to live with the double DLL version.

                      • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                        vincent.spaa

                        Daphne, could you help me out one more time?

                         

                        As I said above, it worked just fine. But that was on my development environment, as soon as I deployed it on-site, it didn't work.

                        This has to do with a slight version difference as I'm running AF server 2.6 locally (with DataLink 2013 and AF Explorer 2012) whereas the customer is running AF server 2.5.0 (with DataLink 2013 and AF Explorer 2012).

                        When I upload both the .Net 4 and .Net 2 version of my Data Reference on that server, Processbook works fine but both the AF Explorer and DataLink don't. They only show the value of today. Which is because (after some debugging) they are passing (null, null, null, null) to GetValue. And it seems DataLink and the AF Explorer receive the .Net 2 version of my Data Reference from the server instead of the .Net 4 version, I'd expect them to get the .Net 4 version.

                        Additionally, if I only upload the .Net 4 version both the AF Explorer and DataLink work fine, but Processbook doesn't.

                         

                        Do you have any more advice?

                          • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                            dng

                            Hi Vincent,

                             

                            What are the .NET frameworks targeted for your data references? Within each data reference, which version of AF SDK (2.0 or 4.0) are you using? Do you have the same GUID for both versions of the data references?

                            You shouldn't have to unregister any existing data references if you use the /force parameter to register the second data reference (with the lower version). After registering both data references on customer's machine, did you see both registering under the same assembly (run RegPlugIn -List)?

                             

                            e.g.

                            2015-02-24 12_34_12-DNG-CODE - Remote Desktop Connection Manager v2.2.png

                             

                            On the client machine, if you look at the %ProgramData%\OSIsoft\AF\PlugIns folder, do you see both versions of the PlugIns? Do you see your 4.0 plugin in the 4.0 folder?

                            1 of 1 people found this helpful
                              • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                                vincent.spaa

                                So this is how it looks like on the customer's server (on the 2.5.0 AF server):

                                temp.PNG

                                And this is how it looks like on my development machine (with a 2.6 AF server):

                                temp2.PNG

                                When I start the PI AF Client on the client machine and open up the folder under ProgramData there is one version of my assembly in a 1.0.0.0 folder and it's the .NET 2.0 assembly.

                                The 4.0 subfolder is nowhere to be found in the ProgramData folder, on the client machine. The PI AF Client should be using the .NET 4.0 version of my DR, right?

                                 

                                To answer your other questions, I have the exact same GUID for both DR versions. And I'm building one version against the .NET 2.0 version of the AF SDK and the other against the .NET 4.0 version of the AF SDK.

                                The command I use to register both assemblies is:

                                RegPlugIn64 PlugIns\MagionUniverse.AFDataReference.ShiftSchedule.dll PlugIns\4.0\MagionUniverse.AFDataReference.ShiftSchedule.dll

                                  • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                                    David Hearn

                                    What is the output of the RegPlugIn command? From your listing you are only getting the first DLL registered. My guess is that you are getting a warning that it cannot find the plugin associated with the second assembly on the command line (the  .NET 4 version). You might have better luck if you run the RegPlugIn from the 'PlugIns' folder so that the '4.0' folder is a direct sub-directory or specify the '/RootDirectory' parameter so RegPlugIn knows where the relative root directory starts.

                                     

                                    RegPlugIn tries to determine the relationship between files specified on the command line automatically, but when it cannot you must specify additional parameters.

                                    • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                                      dng

                                      Hi Vincent,

                                       

                                      I think I figured out what your issue is. For your two CDR plug-ins, not only do they need the exact GUID, they also need the same Assembly ID. From the screenshot you showed, your 2.0 plug-in's assembly ID is 07e4487e-... and your 4.0 plugin's assembly ID is 35411c89-.... They are not matching. Therefore, you will have trouble registering both plugins under the same GUID. Can you copy the assembly information from one to the other so they are matching? One way to do so in visual studio is to click on the project properties and expand on the assembly information. The GUID there is the Assembly ID that RegPlugIn looks at.

                                       

                                      From the RegPlugIn /list output, you can see which version of the plugin is missing (e.g. you are missing the 2.0 version on your dev machine, but missing the 4.0 version on the client machine). After fixing the Assembly ID, register the missing plugin by running RegPlugIn with the /force parameter. You should then be able to register the other plugin. Then run RegPlugIn /list again to confirm.

                                       

                                      Alternatively, unregister your existing plug-ins (using /unregister flag). Then register both plugins (with same assembly ID) using your same command:

                                           RegPlugIn64 PlugIns\MagionUniverse.AFDataReference.ShiftSchedule.dll PlugIns\4.0\MagionUniverse.AFDataReference.ShiftSchedule.dll

                                      Verify using RegPlugIn /list.

                                       

                                      Please let me know if you run into any issues.

                                      1 of 1 people found this helpful
                                  • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                                    David Hearn

                                    You can regplugin with the /List option to see how your plugins are registered in the server. You should see your plugin registered similar to the PIPoint DataReference (it has a .NET 3.5 and .NET 4 version). You should have 2 support assemblies listed where the .NET 3.5 assembly does not have a sub-directory and the .NET 4 assembly should be in a '4.0' sub-directory.

                                     

                                    If this is not how your plugin registration looks, then tell use how you are registering your plugin.

                            • Re: How can I handle 1-1-1970 being passed to my GetValue method?
                              Rick Davin

                              This won't answer your question, but your GetValue could be improved with:

                               

                              public override AFValue GetValue(object context, object timeContext, AFAttributeList inputAttributes, AFValues inputValues)
                              {
                                  CheckConfig();
                              
                                  AFTime time = timeContext == null
                                              ? AFTime.Now
                                              : (AFTime)timeContext;
                              
                                  return Calculate(time.LocalTime);
                              }